Win a copy of Kotlin in Action this week in the Kotlin forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Floating point accuracy  RSS feed

 
Hanna Habashy
Ranch Hand
Posts: 532
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hello:

Why the floating point in a BigDecimal number is not accurate?

BigDecimal num = new BigDecimal(2.001);

The above number (2.001) will actually be stored as 2.009999999977887

Can someone explain why?

Thanks
 
Paul Sturrock
Bartender
Posts: 10336
Eclipse IDE Hibernate Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Not an advanced question. Moving...
 
marc weber
Sheriff
Posts: 11343
Java Mac Safari
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Hanna Habashy:
...Why the floating point in a BigDecimal number is not accurate? ...

It's because the primitive double you passed to the BigDecimal constructor cannot be stored accurately. See the API documentation for BigDecimal(double val), which will describe the problem and the solution.
 
Hanna Habashy
Ranch Hand
Posts: 532
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Marc, thanks for your reply.

I was looking for more of mathematical explanation. I read the api, and there are few ways to store the accurate number. The api faild to expain why such inaccuracy is happening, however.
 
Ulf Dittmer
Rancher
Posts: 42972
73
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The JavaBeginnersFaq page #20 links to two articles that explain this phenomenon well.
 
Kaydell Leavitt
Ranch Hand
Posts: 690
Eclipse IDE Firefox Browser Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Why the floating point in a BigDecimal number is not accurate?
BigDecimal num = new BigDecimal(2.001);


I think that this was a good question. I've known about base-conversion and rounding errors, but I thought that I read that everything would be precise if you only used BigDecimal instead of the primitive double.

I think that I might just stick with using primitive doubles and use my functions to compare them instead of using Java's relational operators. My comparison methods count doubles that are very close as being equal.

Since BigDecimal isn't always accurate either, I might just as well use doubles.
[ May 23, 2007: Message edited by: Kaydell Leavitt ]
 
Hanna Habashy
Ranch Hand
Posts: 532
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The JavaBeginnersFaq page #20 links to two articles that explain this phenomenon well.


Thanks
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
[Kaydell]: I've known about base-conversion and rounding errors, but I thought that I read that everything would be precise if you only used BigDecimal instead of the primitive double.

I'm not sure where a statement like that might be found. BigDecimal is generally more accurate. But still some values fundamentally cannot be stored in decimal form without infinite memory, e.g. 1.0/3.0 = 0.33333... This is why BigDecimal's divide() method is overloaded with versions encouraging you to specify the scale of the answer. Decimal division is inherently prone to require roundoff at some point, and so the recurring question is, how precise do you want it?

In the case Hanna showed, the inaccuracy really comes from the primitive double that was used in the BigDouble constructor. BigDouble's toString() is simply giving a more precise string representation of the inaccurate value that 2.001 represents. If you want a BigDecimal that really means exactly 2.001, use one of the other constructors, e.g. using String:
 
fred rosenberger
lowercase baba
Bartender
Posts: 12542
48
Chrome Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
everything would be precise if you only used BigDecimal instead of the primitive double.

in the example in the original post, they did NOT only use BigDecimals. that 2.001 is considered a double. this is inherently not accurate. The value must be rounded to a value that a double CAN hold, and it is this inaccuracte value that gets passed into BigDecimal.
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!