-1

While running kmeans clustering in java the absolute difference between the data points 0.33 and 0.99 is displayed as 0.659999999 instead of 0.66.

Why is that?

Both the variables holding the data are of type double and I am using the Math.abs() function.

I saw such a problem only for 0.99. When subtracting using other values, the results were fine.

Thanks for any help

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Binoy Dalal
  • 866
  • 10
  • 25
  • 8
    See [Floating Point Arithmetic: Issues and Limitations](http://docs.python.org/3/tutorial/floatingpoint.html) - the article is from the Python docs, but the issue is language-independent. Binary floating points can't accurately store decimal floating point numbers in many cases. – Tim Pietzcker Mar 28 '14 at 08:48
  • This video explains this very well. https://www.youtube.com/watch?v=PZRI1IfStY0 – dburner Mar 28 '14 at 08:49
  • @Jakob: Even your abacus (and your fingers+toes too) have only a finite number of bits available ;-P – JensG Mar 28 '14 at 08:57
  • @JensG yes but adding using my fingers gives correct results, and not 1 finger + 1 finger = 1.99999899 fingers :) – Jakob Mar 28 '14 at 08:59
  • Never ever never, no matter what forever! –  Mar 28 '14 at 09:01

3 Answers3

3

Floating-point datatype (float and double) can't be accurately represented in memory bits. They are approximately represented in memory.

Squeezing infinitely many real numbers into a finite number of bits requires an approximate representation. Although there are infinitely many integers, in most programs the result of integer computations can be stored in 32 bits. In contrast, given any fixed number of bits, most calculations with real numbers will produce quantities that cannot be exactly represented using that many bits. Therefore the result of a floating-point calculation must often be rounded in order to fit back into its finite representation. This rounding error is the characteristic feature of floating-point computation

What Every Computer Scientist Should Know About Floating-Point Arithmetic

Abimaran Kugathasan
  • 31,165
  • 11
  • 75
  • 105
  • 2
    If you don't mind, can you explain why `Math.abs(new Float(0.33-0.99))` return `0.66` instead? – DnR Mar 28 '14 at 08:54
2

This is how floating point numbers behave. They are not accurate.

Check this:- What Every Computer Scientist Should Know About Floating-Point Arithmetic

Also to add Floating point numbers use binary fractions and not decimal fractions. And if you need exact decimal values, you should use java.math.BigDecimal

You may check this answer as well for more reasoning and details:

Floating point rounding errors. 0.1 cannot be represented as accurately in base-2 as in base-10 due to the missing prime factor of 5.

Community
  • 1
  • 1
Rahul Tripathi
  • 168,305
  • 31
  • 280
  • 331
1

Doubles are not exact due to the way they are stored in memory. More information here: https://en.wikipedia.org/wiki/Double-precision_floating-point_format

If you need an exact result, you should look into BigDecimal

Gijs Overvliet
  • 2,643
  • 3
  • 28
  • 35
  • BigDecimal is no more exact than `double`. It is only exact for a different set of numbers. – Pascal Cuoq Mar 28 '14 at 08:55
  • 1
    Could you back that claim up? Because, as far as I know, BigDecimal IS more exact. From the documentation: "When a MathContext object is supplied with a precision setting of 0 (for example, MathContext.UNLIMITED), arithmetic operations are exact, as are the arithmetic methods which take no MathContext object." – Gijs Overvliet Mar 28 '14 at 08:59
  • Note: I didn't say it wasn't “more exact”. I said it was exact for a different set of numbers than `double` (`double` is exact for lots of numbers and it is possible to do long sequences of exact `double` computations if you know what you are doing), and that “If you need an exact result, you should look into BigDecimal” was a mischaracterization. Let me put it this way: I would like the exact result of 1 divided by 3. It is a waste of time to “look into BigDecimal” for this elementary operation. It won't work. – Pascal Cuoq Mar 28 '14 at 09:51
  • Point taken. "In the case of divide, the exact quotient could have an infinitely long decimal expansion; for example, 1 divided by 3. If the quotient has a nonterminating decimal expansion and the operation is specified to return an exact result, an ArithmeticException is thrown." - However, you can specify the amount of decimals you want to see (up to 4679 digits, what I've tested), making it far more exact than a Double. – Gijs Overvliet Mar 28 '14 at 10:04
  • You mean “far more precise than a double”. Either a representation is exact or it isn't. – Pascal Cuoq Mar 28 '14 at 10:08