Apparently identical math expressions with different outputs

The following code will produce different results for the variables "e" and "f" on a 32-bit x86 machine, but the same results on a 64-bit x86 machine. What for? Theoretically, the same expression is evaluated, but technically it is not.

#include <cstdio> main() { double a,b,c,d,e,f; a=-8988465674311578540726.0; b=+8988465674311578540726.0; c=1925283223.0; d=4294967296.0; e=(c/d)*(ba)+a; printf("%.80f\n",e); f=c/d; f*=(ba); f+=a; printf("%.80f\n",f); } 

Note ... 32-bit x86 code can be generated using "gcc -m32", thanks @Peter Cordes https://stackoverflow.com/users/224132/peter-cordes

see also

: boost :: random :: uniform_real_distribution should be the same for all processors?

--- update for Madivad user

 64 bit output -930037765265417043968.00000... -930037765265417043968.00000... 32 bit output -930037765265416519680.00000... -930037765265417043968.00000... 

The "mathematically correct" output can be set using this python code

 from fractions import Fraction a=-8988465674311578540726 b=8988465674311578540726 c=1925283223 d=4294967296 print "%.80f" % float(Fraction(c,d)*(ba)+a) -930037765265416519680.000... 
+6
source share
1 answer

FLT_EVAL_METHOD .

C allows intermediate FP calculations on higher / wider types depending on FLT_EVAL_METHOD . Therefore, when wider types are used and the code flow is different, albeit mathematically equal, slightly different results may occur.


With the exception of assignment and casting (which removes all additional range and accuracy), the values ​​obtained by operators with floating operands and values ​​subject to ordinary arithmetic conversions and floating constants are evaluated in a format whose range and accuracy may be greater than what is required by type. The use of evaluation formats is characterized by the implementation-specific value FLT_EVAL_METHOD :

-1. indefinable;
0. evaluate all operations and constants only by range and type accuracy; 1. Evaluate operations and constants of type float and double the range and precision of a double type, evaluate long dual operations and constants in the range and precision of a long double type.
2. Evaluate all operations and constants in the range and accuracy of the long double type.
C11dr §5.2.4.2.2 9

[change]

@Pascal Cuoq has a helpful commentary about the veracity of FLT_EVAL_METHOD . In any case, FP code optimized for different code paths can present different results. This can happen if FLT_EVAL_METHOD != 0 or the compiler does not comply with strict compliance.

Regarding the details of the message: the operation X*Y + Z , performed in 2 operations * , and then + can be contrasted with fma() , which "calculates (x × y) + z, is rounded as one triple: they calculate value (as if) to infinite precision and rounded once to the format of the result in accordance with the current rounding mode. " C11 §7.12.13.1 2. Another candidate for a difference in results may be caused by applying "fma" to the line e=(c/d)*(ba)+a;

+10
source

All Articles