Precision of floating numbers is limited, detailed description can be found in the AS Help.
REAL: B&R Online Help
LREAL: B&R Online Help
There are several sources in the web explaining reason for limited precision of floting numbers in detail (google for “float precision”). Already 0.01 e.g. is only representable with limited precision with datatype REAL.
Handling on PLC:
Be aware of rounding errors in your calculations
Don’t do comparison (IF SomeREAL = 0.1 THEN …) of floating numbers
Differences C vs. ST: C uses per default double/LREAL (8 byte) precision while ST uses per default float/REAL (4 byte) precision.
Sample for saving 0.01 into a LREAL variable SomeLReal_C / SomeLReal_ST:
SomeLReal_C = 0.01; // (8 byte precision) Result = 0.01
SomeLReal_C = 0.01F; // (4 byte precision) Result = 0.00999999...
SomeLReal_ST := 0.01; // (4 byte precision) Result = 0.00999999...
SomeLReal_ST := LREAL#0.01; // (8 byte precision) Result = 0.01
Use-cases/Samples:
Saving values into a XML file using MpRecipe leads to “wrong” representation:
LREAL := 660.4; // => final value in the XML file = 660.39999999999998
=> This is normal behaviour, caused by limited precision of LREAL / DOUBLE (8 byte).
Library AsBrStr, brsatof is used to convert STRING into REAL, but the FUB does not correctly convert the value:
This is great information to have out in the community. I use a website to demonstrate the precision of IEEE 754 to myself and others.
Link: IEEE-754 Floating Point Converter
The basic example is to enter 0.2 and see the error due to how the floating point must be stored in base-2 computing.
Added bonus is the hexadecimal representation, which helps if you are looking at unformatted data (such as coming across a communication bus) to find the floating point value.
What is the correct way of checking if a floating point value can cause a division by zero error in B&R?
It depends on if you only want divide by zero error protection or want reasonable limits as well. Only true 0.0 will produce a fatal error, but 1.0 / 1.17E-38 isn’t likely to yield a usable result.
I’ve never seen a fatal error because of a floating-point division. How / where does it happen? Does it need a specific CPU?
I would have said it’s not CPU specific and is floating-point universal, but it’s been a long while since I caused one . The errors I am thinking of are 9104/25300 and are critical exceptions (reboot into SERVICE mode). See B&R Online Help - 9104 (br-automation.com), B&R Online Help - 25300(br-automation.com). You can also see (possibly vestigial) functions in the IECChk library.
However, this information appears to be outdated, or at the very least, incomplete. Testing in both ARSim and AREmb (AR 4.83 - Intel Atom CPU) results in the positive/negative/NaN indicated by Patrick.
The errors mentioned there do still exist and these are for integers. For integers they make sense, as there is no way to display these special values in integer representation. So, the info is not outdated. However, Arm processors don’t even have these exceptions for integers and just return 0.
Yes, I stumbled on that once, when I made a GetNan() function in ST, as there is no constant or function existing in the IEC system. Obviously the IecCheck did’t like
FUNCTION GetNan
GetNan := 0.0 / 0.0;
END_FUNCTION
For some users the division check for REAL might be ok, but dividing by 0 can be a real use case.