Search code examples
scalamathprecisionbigdecimalbigint

Scala BigDecimal - loss of precision


I need to do some precision calcs with Big Numbers and I have been trying with Scala BigDecimal but I have noted loss of precision.

As an example:

2^63 == 9223372036854775808
2^64 == 18446744073709551616

However when I do

println(BigDecimal.decimal(scala.math.pow(2, 63)).toBigIntExact())
println(BigDecimal.decimal(scala.math.pow(2, 64)).toBigIntExact())

I get

9223372036854776000 != 9223372036854775808
18446744073709552000 != 18446744073709551616 

I don't know if I can get the exact BigInt.

Maybe I have to take other approach.

Could anyone help me to fix this issue?


Solution

  • @ scala.math.pow(2, 63)
    res0: Double = 9.223372036854776E18
    

    You get Double on math.pow, and then you pass the result to BigDecimal - it means that you lost precision even before you started using Big* classes.

    If you put numbers into BigDecimal when they are still small and haven't yet lost precision (and if you use the constructors correctly) then you'll get the expected result:

    @ BigDecimal(2).pow(63).toBigInt
    res4: BigInt = 9223372036854775808
    
    @ BigDecimal(2).pow(64).toBigInt
    res5: BigInt = 18446744073709551616
    
    @ BigDecimal(2).pow(63).toBigIntExact
    res6: Option[BigInt] = Some(9223372036854775808)
    
    @ BigDecimal(2).pow(64).toBigIntExact
    res7: Option[BigInt] = Some(18446744073709551616)