Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to confirm whether different results are due to differences in floating point handling?

I have converted a relatively simple algorithm that performs a large number of calculations on numbers of the double type from C++ to Java, however running the algorithm on the two platforms but the same machine produces slightly different results. The algorithm multiplies and sums lots of doubles and ints. I am casting ints to double in the Java algorithm; the C algorithm does not cast.

For example, on one run I get the results:

  • (Java) 64684970
  • (C++) 65296408

(Printed to ignore decimal places)

Naturally, there may be an error in my algorithm, however before I start spending time debugging, is it possible that the difference could be explained by different floating point handling in C++ and Java? If so, can I prove that this is the problem?


Update - the place where the types differ is a multiplication between two ints that is then added to a running total double. Having modified the C code, currently in both:

mydouble += (double)int1 * (double)int2

like image 255
brabster Avatar asked Mar 01 '12 15:03

brabster


People also ask

What every programmer should know about floating-point numbers?

Floating-point representations have a base (which is always assumed to be even) and a precision p. If = 10 and p = 3, then the number 0.1 is represented as 1.00 × 10-1. If = 2 and p = 24, then the decimal number 0.1 cannot be represented exactly, but is approximately 1.10011001100110011001101 × 2-4.

Why are floating-point numbers inaccurate?

Floating-point decimal values generally do not have an exact binary representation due to how the CPU represents floating point data. For this reason, you may experience a loss of precision, and some floating-point operations may produce unexpected results.

What is a floating-point rounding error?

Because floating-point numbers have a limited number of digits, they cannot represent all real numbers accurately: when there are more digits than the format allows, the leftover ones are omitted - the number is rounded.


2 Answers

You could add rounding to each algorithm using the same precision. This would allow each calculation to handle the data the same way. If you use this, it would eliminate the algorithm being the problem as the data would be using the same precision at each step of the equation for both the C++ and Java versions

like image 139
jzworkman Avatar answered Sep 28 '22 01:09

jzworkman


AFAIK there are times when the value of a double literal could change between two c++ compiler versions (when the algorithm used to convert the source to the next best double value changed).

Also on some cpus floating point registers are larger than 64/32bit (greater range and precision), and how that influences the result depends on how the compiler and JIT move values in and out of these registers - this is likely to differ between java and c++.

Java has the strictftp keyword to ensure that only 64/32 bit precision is used, however that comes with a run-time cost. There are also a large number of options to influence how c++ compilers treat and optimize floating point computations by throwing out guarantess/rules made by the IEEE standard.

if the algorithm is mostly the same then you could check where the first difference for the same input appears.

like image 27
josefx Avatar answered Sep 28 '22 01:09

josefx