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:
(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
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.
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.
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.
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With