1.20 + 1.23 = 2.42999997


#1

Why this is happening?


Just saw that when working in intellij, convert to simple operation, thought it was my project settings problem, but no. Visit https://play.kotlinlang.org and still result of this 2 ordinary nubmers not 2.43
Any other sum of double is ok, excatly 1.20 + 1.23 somehow broken
More screenshots: image


#2

It is to do with the way a double is represented in memory, that is why a lot of languages also have a 128biut decimal type where greater precision is required.


#3

See https://floating-point-gui.de/


#4

That is why all actual floating point tests have necessary margin of error.


#5

Because not all decimals can be accurately represented in base 2 (binary). You can do fast math in binary and live with occasional inaccurate representations or slow math using things like BigDecimal. When you represent money or other values that must be exact decimal representations, you can’t use binary floating point math. That’s all languages, not Kotlin-specific.


#6

And by accurate representation, I mean they become repeating decimals. It’s like how 1/3 can’t be represented as an actual number in decimal. It’s 0.33333333…


#7

Also:

No; the issue affects (almost) all decimals, but the way that they’re rounded for display happens to hide the problem in the other cases you’ve tried.

As mentioned above, floating-point numbers are stored as binary floating point (with an integer mantissa, and an integer number of powers of two by which to multiple or divide it). Just as 1/3 can’t be represented exactly as a decimal fraction (0.33333…), so 1/10 doesn’t fit into a binary fraction (0.0001100110011…). So what you start from isn’t 1.23 and 1.20, but a pair of binary floating-point numbers that are very close to 1.23 and 1.20. Ditto their sum.

When you print floating-point numbers out, it picks the nearest decimal fraction — and in many cases, those approximations cancel out. But not always, as you’ve found!

If you want exact results, don’t use floating-point. BigDecimal is far better. (Or, if you need fixed precision, you could multiply all your numbers by that factor and store then as ints. Or some other approach. But BigDecimals are the usual solution — especially in Kotlin, where they’re so easier to use!)


#8

Well, in Java it is same

double q = 1.20 + 1.23;

prints: 2.4299999999999997

So seems to be correct ? Or Java is also broken ?