Reputation: 5540
I have occurred in this strange division error in a grails project (But I think grails has little to do with it, is a groovy or java question I think):
If in the groovy console I run this
float money = -1.30
float r = 0.01
println ((money/r).class.name)
println ((money/r).floatValue())
println ((money/r).toString() )
I get this output
java.lang.Double
-130.0
-129.99999813735482
The float division in groovy give me a Double, and this is correct but why the Double toString() give me a so strange value "-129.99999813735482" and not the correct "-130.0"?
Upvotes: 1
Views: 1375
Reputation: 171144
As everyone says, double
and float
aren't precise enough for what you're trying to do.
One solution is to not use float
as your object type, and do:
def money = -1.30
def r = 0.01
println ((money/r).class.name)
println ((money/r).floatValue())
println ((money/r).toString() )
As you can see, Groovy uses BigDecimal
, which means the output is:
java.math.BigDecimal
-130.0
-130
Upvotes: 5
Reputation: 24895
By doing the floatValue
, you are limiting the precission of the value. So the JVM does a rounding and you get the different value.
And before you say "but 130.0 should be the value calculated because it is the correct one" keep in mind that the computer uses binary format to represent decimal numbers and this causes rounding errors with fractions (try to represent 0.3 in binary to understand why).
Upvotes: 1
Reputation: 346377
From the Floating-Point Guide:
Why don’t my numbers, like 0.1 + 0.2 add up to a nice round 0.3, and instead I get a weird result like 0.30000000000000004?
Because internally, computers use a format (binary floating-point) that cannot accurately represent a number like 0.1, 0.2 or 0.3 at all.
When the code is compiled or interpreted, your “0.1” is already rounded to the nearest number in that format, which results in a small rounding error even before the calculation happens.
Specifically, neither 1.3 nor 0.01 can be accurately represented by a float
.
Upvotes: 6