MoZZoZoZZo
MoZZoZoZZo

Reputation: 243

Are results from math operations on Double exactly repeatable?

I have a complex data processing algorithm implemented using Java 8 and using Double as data type. Given the same input (many hundred thousand database rows) this algorithm outputs different Double values. Sometimes value a is returned, sometimes value b. These two values alternate each execution. The difference between a and b is ~0.0001. I am aware that Double datatype does not grant exact values like Decimal does. I am not sure, however, if it grants repeatable results, assuming exactly same input. I.e. would it be possible that rounding policies are applied in a non-consistent way? My purpose here would be to explain why I get different values with same input.

Other details: I am using Tomcat 8 runtime environment, deployment done on SAP HCP. Datatype at database level is Decimal, we need Double at Java level for historical reasons.

Upvotes: 4

Views: 1006

Answers (4)

Patricia Shanahan
Patricia Shanahan

Reputation: 26185

For strictfp the Java Language Specification fully defines the results of all simple arithmetic on doubles, regardless of platform.

Some java.lang.Math methods are allowed to produce slightly different results for some operations. If you need reproducible results, use java.lang.StrictMath instead.

As noted in a comment below, java.lang.Math.cos is an example of a function whose result can change. The API documentation says "The computed result must be within 1 ulp of the exact result. Results must be semi-monotonic."

Upvotes: 4

Eugene
Eugene

Reputation: 120968

This is an example from the doc of Collectors.averagingDouble:

The average returned can vary depending upon the order in which values are recorded, due to accumulated rounding error in addition of values of differing magnitudes.

The key words here are depending upon the order. This is because average double uses Kahan summation under the hood (for better results and less lost precision).

The same counts for any other double operation. The order in which those operations are applied could have an impact on the final result (because of rounding).

Here is an example:

  Double d1 = Stream.of(10000.0D, 3.14159D, 2.71828D).collect(Collectors.averagingDouble(x -> x)); 
  Double d2 = Stream.of(3.14159D, 10000.0D, 2.71828D).collect(Collectors.averagingDouble(x -> x));


  System.out.println(d1); // 3335.2866233333334
  System.out.println(d2); // 3335.286623333333

Same numbers applied in different order gives a different result (precision is now different)

Upvotes: 3

Markus Benko
Markus Benko

Reputation: 1507

Order matters. If the order of the database rows processed is not the same every time it can yield different results. Here is a simple example:

double d1 = 0.1;
double d2 = 0.2;
System.out.println(d1 + d1 + d2 + d2); 
System.out.println(d1 + d2 + d2 + d1); 

Upvotes: 9

Thilo
Thilo

Reputation: 262714

Given the same input, floating point number calculations (on the same platform) will result in the same output.

However, you may get different results if you feed in the input numbers in different orders (even though that would not make a difference mathematically). Maybe that is what is happening here (seeing that you pull the numbers out of a relational database, which has no defined order unless you explicitly sort). Same thing can happen if you have parallel computations using multiple CPU and the data is divided and combined differently each time.

Upvotes: 9

Related Questions