Search code examples
groovybigdecimal

Groovy BigDecimal Precision Problem


given the following line

BigDecimal step = 10.0G**-1.0G

groovy 1.7.5 returns the wrong

0.1000000000000000055511151231257827021181583404541015625

and groovy 1.8 returns the correct

0.1

Unfortunately, I want to solve my Problem in Grails. 1.4 with groovy 1.8 isn't stable enough yet (controllers are not refreshed in dev mode) and grails 1.3.7 comes with groovy 1.7.x

two questions:

  • am I doing something wrong or is it a bug in 1.7.5?

  • how can I avoid this behaviour? I though BigDecimals where perfect for this kind of rounding problem?

second update: (forget the first update)-;

I now get a bit confused. seems that I get different result every time I try....:

BigDecimal step = 10.0G**-1.0G
println step

returns 0.1000000000000000055511151231257827021181583404541015625

and

println 10.0G**-1.0G

returns

0.1

in both groovy versions.

But if you just put BigDec step = 10.0G**-1.0G in the groovyConsole and let the console print the last response, you get the different results for different groovy versions. So one problem seems to be the groovyConsole.

Another Problem seems to be the toString conversion which is performed.

And it seems that some autoboxing is involved... when I do a

def step = 10.0G**-1.0G

the result is a Double...

I guess this boils the problem down to two questions:

  • a) which math operations are BigDecimal operations?

and

  • b) how can I easily round a BigDecimal so that I can correct the above problem?

Thanx for your patience


Solution

  • I guess I've got it. Here is the clue from the java doc:

    BigDecimal(double val) Translates a double into a BigDecimal which is the exact decimal representation of the double's binary floating-point value.

    • So, the Math.-Functions I use in my code seem not to support BigDecimal.
    • the result is converted behind the scenes from Double to BigDecimal
    • exact representation of the double's binary is 0.1000000000000000055511151231257827021181583404541015625 when the double is 0.1
    • println 10.0G**-1.0G prints the double value (0.1)
    • BigDecimal step = 10.0G**-1.0G; println step prints the BigDecimal representation of the double 0.1which is the ugly number above

    It seems that there is no difference in the behaviour of the groovy versions (with regard to the BigDecimals), but there is a difference in the behaviour of how the result is output in the groovyConsole.