Applies To:
  • CitectSCADA 4.xx, 5.xx

I have a numeric tag of type REAL on a Citect page. I want to format the value to 2 decimal places. The number 16.335 displays as 16.33 rather than 16.34, while 15.335 displays correctly as 15.34. I have tried both the Format section in the Text Properties box and the Round() function.

Also, we get the problem of incorrect comparisons when we write to and read from the PLC with the following;

1. We have a string set point, this is written to a tag via tag = Round(StrToReal(string),2)

2. We Sleep() for the tag to be UNSCALED and written to the PLC as an integer ( tag is scaled from 0 -1000 to 0 -10.00 )

3. Then we ReRead and make sure data is correct, using IF Tag:#.## <> StrtoReal(String):#.## THEN fault

4. or we use IF Tag <> Round(StrToReal(string),2) THEN fault

What's going on?


In our above example there are three areas that may yield minor inaccuracy, tag = Round(StrToReal(string),2) may not always yield the same value. Then the tag scaling from an INT to a number with decimal places, scaled from 0 -1000 to 0 -10.00 will also yield minor inaccuracy as Citect converts this to a floating point number. And then, comparing real numbers should never be done in cicode for the following reasons.

Citect uses the IEEE 32 bit floating number format for tags of type real. This standard guarantees 7 digits of precision. The reason for this is because decimal fractions often can't be represented exactly in binary, and so must be approximated. When you enter the number 16.335 it is stored as 16.334999084473. When this number is rounded to 2 decimal places the value is 16.33. The number 15.335 is stored as 15.335000038147 and so gets rounded to 15.34 as expected.

See Q2647 for a detailed description of precision for real numbers in Citect. Also from the MS Kbase Article ID: Q125056 states;

Never compare two floating-point values to see if they are equal or not equal. There are almost always going to be small differences between numbers that "should" be equal. Instead, always check to see if the numbers are nearly equal. In other words, check to see if the difference between them is very small or insignificant.

As an example; calculate the smallest possible difference between two numbers close to 1.0.

x = 1.00000000000000000 (one bit more than 1.0)

y = 1.00000000000000000 (exactly 1.0)

x-y = .00000000000000022 (smallest possible difference)