Clang with default settings seems to get it right: https://imgur.com/a/d3LBlLK
GNU GCC does not round floating-point divisions to the nearest value
21–30 of 87 posts
Re: GNU GCC does not round floating-point divisions to the nearest value
#22Perhaps the title should mention that this is 32-bit x86, which is rather obsolete. This should work okay on x86_64.
Are you sure? The FPU instruction set is the same.
Re: GNU GCC does not round floating-point divisions to the nearest value
#23If you add '-ffast-math' to the compiler parameters in his godbolt link you get the 'right' answer. Doing that means the division is done with the 'divsd' instruction, which clang uses even without the 'fast-math' flag. That doesn't mean it's necessarily the right thing to do though. Clang can be made generate the same code as the 'broken' gcc output by declaring the variables as 'long double' instead of 'double'. So…
-ffast-math should rebrand itself to -ffast-and-more-correct-math ;)
Re: GNU GCC does not round floating-point divisions to the nearest value
#24I believe the issue is that some of this ends up evaluated at compile-time, and the compiler really has no idea how to do rounding correctly at that point. When implementing floating point tests for an x86 emulator, we had to create a macro that would ensure that the calculation was done at runtime rather than at compile time for this exact reason: https://github.com/ish-app/ish/blob/18176b6931d69bdabe48f137... . If…
Re: GNU GCC does not round floating-point divisions to the nearest value
#25Perhaps the title should mention that this is 32-bit x86, which is rather obsolete. This should work okay on x86_64.
Are you sure? The FPU instruction set is the same.
Re: GNU GCC does not round floating-point divisions to the nearest value
#26Re: GNU GCC does not round floating-point divisions to the nearest value
#27[1]:https://www.khronos.org/registry/OpenCL/specs/2.2/html/OpenC...
Re: GNU GCC does not round floating-point divisions to the nearest value
#28Perhaps the title should mention that this is 32-bit x86, which is rather obsolete. This should work okay on x86_64.
Are you sure? The FPU instruction set is the same.
I originally had the wrong answer here, but I'm including below for historical purposes and embarrassment. Re-reading on my laptop meant I didn't misread/read-the-expected?
Basically by default when compiling for IA32 gcc assumes that there is no SSE unit, and so must use the x87 fpu.
Alas the x87 unit doesn't have either 32 or 64 bit ieee floating point types, so the calculation at runtime must be rounded to float/double at the end of the computation. That results in a double round that is incorrect.
Minor additional comment - x87's reduced precision modes (that reduce mantissa precision to ieee754-32/64) don't reduce the exponent size so it's conceivable you could get multiple-rounding derived errors even then. But no one would be toggling x87 state like that anyway, so theoretically not something that would matter in most cases.
Old incorrect answer:
On ia32 long double is the x87 80bit ieee754 numeric type.
On x86_64 on windows, and maybe Linux, long double is just a 64bit ieee float.
So my guess is that GCC computes constant evaluation of floating point expressions in “long double” for maximum precision, and then rounds to the required precision at the end. This is not valid going from 64->32 bit floats and you could probably induce this bug if you tried hard enough.
Anyway it is not sound to round twice in any numeric operation, and by doing the calculation at one precision and then rounding that to the required precision that is what gcc is doing.
This is a bug in GCC, floating point is well defined, there isn’t randomness to it, and they’ve introduced additional rounding that is not valid.
Re: GNU GCC does not round floating-point divisions to the nearest value
#29The only way of doing FP on x86 and keeping your sanity is by making sure you use 32/64 bit floats 100% of the time. That is: use SSE registers and never the 80-bit x87 arithmetic.
I thought compilers for 64 bit programs these days did exactly this. I know the .NET Jit does for example.
Re: GNU GCC does not round floating-point divisions to the nearest value
#30The behavior appears to be consistent with the standard. Keep in mind that GCC needs to provide the same result irrespective of the architecture it runs on and one reason to use GCC for floating point is to take advantage of dedicated hardware. And the reason to use floating point is speed not precision (at least when using decimal floating point). If precision is critical then arbitrary precision or fixed point is the way to go. Normally it isn’t that critical.