Expand Authors Top

If you have a few years of experience in the Java ecosystem and you’d like to share that with the community, have a look at our Contribution Guidelines.

November Discount Launch 2022 – Top
We’re finally running a Black Friday launch. All Courses are 30% off until next Friday:


November Discount Launch 2022 – TEMP TOP (NPI)
We’re finally running a Black Friday launch. All Courses are 30% off until next Friday:


Expanded Audience – Frontegg – Security (partner)
announcement - icon User management is very complex, when implemented properly. No surprise here.

Not having to roll all of that out manually, but instead integrating a mature, fully-fledged solution - yeah, that makes a lot of sense.
That's basically what Frontegg is - User Management for your application. It's focused on making your app scalable, secure and enjoyable for your users.
From signup to authentication, it supports simple scenarios all the way to complex and custom application logic.

Have a look:

>> Elegant User Management, Tailor-made for B2B SaaS

1. Overview

In this quick article, we're going to have a look at why changing the sum order returns a different result.

2. Problem

When we look at the following code, we can easily predict the correct answer (13.22 + 4.88 + 21.45 = 39.55). What is easy for us, might be interpreted differently by the Java compiler:

double a = 13.22;
double b = 4.88;
double c = 21.45;

double abc = a + b + c;
System.out.println("a + b + c = " + abc); // Outputs: a + b + c = 39.55

double acb = a + c + b;
System.out.println("a + c + b = " + acb); // Outputs: a + c + b = 39.550000000000004

From a Mathematical point of view, changing the order of a sum should always give the same result:

(A + B) + C = (A + C) + B

This is true and works well in Java (and other computer programming languages) for integers. However, almost all CPUs use for non-integer numbers IEEE 754 binary floating point standard, which introduces inaccuracy when decimal number is stored as the binary value. Computers can't represent all real numbers precisely.

When we change the order, we also change the intermediate value that is stored in the memory, and thus the result may differ. In the next example, we simply start with either sum of A+B or A+C:

double ab = 18.1; // = 13.22 + 4.88
double ac = 34.67; // = 13.22 + 21.45
double sum_ab_c = ab + c;
double sum_ac_b = ac + b;
System.out.println("ab + c = " + sum_ab_c); // Outputs: 39.55
System.out.println("ac + b = " + sum_ac_b); // Outputs: 39.550000000000004

3. Solution

Because of notorious inaccuracy of floating point numbers, double should never be used for precise values. This includes currency. For accurate values, we can use BigDecimal class:

BigDecimal d = new BigDecimal(String.valueOf(a));
BigDecimal e = new BigDecimal(String.valueOf(b));
BigDecimal f = new BigDecimal(String.valueOf(c));

BigDecimal def = d.add(e).add(f);
BigDecimal dfe = d.add(f).add(e);

System.out.println("d + e + f = " + def); // Outputs: 39.55
System.out.println("d + f + e = " + dfe); // Outputs: 39.55

Now we can see that in the both cases results were the same.

4. Conclusion

When working with decimal values, we always need to remember that floating point numbers are not represented correctly, and this can cause unexpected and unwanted results. When precision is required, we must use BigDecimal class.

As always, the code used throughout the article can be found over on GitHub.

November Discount Launch 2022 – Bottom
We’re finally running a Black Friday launch. All Courses are 30% off until next Friday:


Generic footer banner
Comments are closed on this article!