Am I crazy? A-B [REAL] give wrong result?

hki75
2017-09-14
2017-09-28
  • hki75 - 2017-09-14

    a simple code:
    PROGRAM PLC_PRG
    VAR
    A: REAL:=50.0;
    B: REAL:=50.15;
    C:REAL;
    END_VAR

    C:=A-B;

    C value is -0.1500015 ? Why?

    I'm using 2.3.9.53

    IMG: 14

     
  • Anonymous - 2017-09-14

    Originally created by: scott_cunningham

    Accuracy limits of REAL type. If you need higher accuracy, then you need to use LREAL, if it is supported on your platform.

     
  • hki75 - 2017-09-15

    mmm....I don't think is the REAL data type limit...by doing the same calculation on codesys 3 is ok. Or by trying to adding (50+50.15=100.15 , not 100.1500015..)the result is correct. I think is something related to the fraction and exponent management ...
    No one had the same trouble?

     
  • Anonymous - 2017-09-18

    Originally created by: scott_cunningham

    You are hitting accuracy errors. Keep in mind that 0.15 is a repeating number in base 2, so depending on internal implementation, you will have an error when you define the value because of truncation. Also, I am pretty sure you will see more accuracy problems with 50-50.15 (negative, fractional number) than with 50 + 50.15. This page (http://ccm.net/contents/62-representati ... d-integers) gives an explanation of how real numbers are stored as a 32 bit number.

    This calculator (https://baseconvert.com/) shows:

    -0.1500000 = -0.0010 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 1
    -0.1500015 = -0.0010 0110 0110 0110 0111 1111 1001 0000 1101 1001 1101 0111 0111 0111 0100 1010 1
    

    Bit deviation starts at bit 20 (23 bits would be absolute max performance, based on 23 bit mantissa)

    Now, if we look at your 50-50.15:

    50.00 = 11 0010.0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0
    50.15 = 11 0010.0010 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 1
    

    50.00 will be: 1.10010000000000000000000 e^(127+5) s=0, m=10010000000000000000000, e=10000100
    50.15 will be: 1.10010001001100110011001 e^(127+5) s=0, m=10010001001100110011001, e=10000100

    Ultimately, you are subtracting a truncated repeating number, so error will appear sooner.

    I created a project with CoDeSys 3.5.6.66 that has an error already with 50.15 (as expected) - see the screen shot. I also used 50.5 instead, and received a "perfect" answer (because 0.5 is 0.1 in base 2 notation). See screen shots.

    Are you sure your CoDeSys 3 test was still using 32 bit REALs? With LREAL, you will see -0.15 in the online debug mode, but not in the variable header - you will see truncation error of infinite repeating 0.15 in base 2:

    IMG: errors.png

    IMG: clean.png

    IMG: lreal.png

     
  • shooter - 2017-09-28

    REAL is not exact, so you can see a small deviation.
    the same can be done on a simple calculator, just add 1 and after 1 million times the result will not be exact.
    It is indeed to do with the way the mantisse works, as it is not endless resolution.

     

Log in to post a comment.