SA0054: Comparisons of REAL/LREAL for equality/inequality

Function

Determines where the comparison operators = (equality) and <> (inequality) compare operands of type REAL or LREAL.

Reason

REAL/LREAL values are implemented as floating point numbers in accordance with the IEEE 754 standard. This standard implies that certain seemingly simple decimal numbers cannot be represented exactly. As a result, the same decimal number may have different LREAL representations.

Sample:

fLREAL_11 := 1.1;
fLREAL_33 := 3.3;
fLREAL_a := fLREAL_11 + fLREAL_11;
fLREAL_b := fLREAL_33- fLREAL_11;
bTest := fLREAL_a = fLREAL_b;

bTest will return FALSE in this case, even if the variables fLREAL_a and fLREAL_b both return the monitoring value "2.2". This is not a compiler error, but a property of the floating point units of all common processors. You can avoid this by specifying a minimum value by which the values may differ:

bTest := ABS(fLREAL_a - fLREAL_b) < 0.1;

Exception

A comparison with 0.0 is not reported by this analysis. For 0 there is an exact representation in the IEEE 754 standard and therefore the comparison normally works as expected. For better performance, it therefore makes sense to allow a direct comparison here.

Importance

High

PLCopen rule

CP54

Samples:

PROGRAM MAIN
VAR
    fREAL1  : REAL;
    fREAL2  : REAL;
    fLREAL1 : LREAL;
    fLREAL2 : LREAL;
    bResult : BOOL;
END_VAR
bResult := (fREAL1 = fREAL1);    // => SA0054 
bResult := (fREAL1 = fREAL2);    // => SA0054
bResult := (fREAL1 <> fREAL2);   // => SA0054
bResult := (fLREAL1 = fLREAL1);  // => SA0054
bResult := (fLREAL1 = fLREAL2);  // => SA0054
bResult := (fLREAL2 <> fLREAL2); // => SA0054
 
bResult := (fREAL1 > fREAL2);    // no error
bResult := (fLREAL1 < fLREAL2);  // no error