Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to ensure same float numbers on different systems?

If I compile following c lines on windows and linux(ubuntu) I get different results. I would like to avoid. How can I do it?

 double a = DBL_EPSILON;
 double b = sqrt(a);
 printf("eps = %.20e\tsqrt(eps) = %.20e\n", a, b);

linux output:

eps = 2.22044604925031308085e-16        sqrt(eps) = 1.49011611938476562500e-08

windows output:

eps = 2.22044604925031310000e-016       sqrt(eps) = 1.49011611938476560000e-008

On linux tested with gcc and clang on 32-bit and 64-bit system same result. On windows tested with gcc-mingw on 32-bit and visual-studio with 32-bit and 64-bit, also same results.

like image 821
Will Avatar asked Nov 26 '12 18:11

Will


1 Answers

In the example you give, it seems both programs have the same floating-point numbers. They just print them differently. The simplest solution around this particular issue is to write your own floating-point printing function. If you are not expecting too nice an output, you could use the function here as pseudocode for writing your own in C. It is not correctly rounded, but it works for what it is intended for (that is, reproducible and readable outputs).


A deeper issue that your question hints you are encountering is floating-point computations giving different results on different platforms. This is a result of the C standard(s) not forcing compilers to implement the IEEE 754 floating-point standard exactly, specifically, allowing higher precision for intermediate results. And this relative leniency of the C standard(s) is caused at least in part by the historical x86 floating-point instructions making it expensive to implement the exact IEEE 754 semantics.

On Linux, assuming you are using GCC, try the -msse2 compilation option. EDIT: the OP commented that -msse2 -mfpmath=sse worked for him. This makes GCC generate modern SSE2 instructions that give the exact IEEE 754 floating-point semantics. If on Windows you are using GCC too, use the same option there.

If you are using Visual C: Visual C uses another trick to force the historical floating-point instructions to match IEEE 754 semantics: it tells the old 80-bit floating-point hardware to use only as many significand bits as IEEE 754 double-precision has. That gives an accurate simulation of double-precision numbers, except for a few corner cases that you will not be encountering. In this case it would help(*) if your program used only double-precision numbers (the C double type).

(*) The Visual C compiler could theoretically generate code that computes exact single-precision arithmetics by rounding each intermediate result from double to single precision, but this would be expensive and I doubt it does this.

like image 71
Pascal Cuoq Avatar answered Sep 20 '22 08:09

Pascal Cuoq