Scala BigDecimal - потеря точности - PullRequest
0 голосов
/ 15 апреля 2020

Мне нужно выполнить некоторые точные вычисления с большими числами, и я пытался с Scala BigDecimal, но я заметил потерю точности.

В качестве примера:

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

Однако, когда я делаю

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

, я получаю

9223372036854776000 != 9223372036854775808
18446744073709552000 != 18446744073709551616 

Я не знаю, если я можно получить точную BigInt.

Может быть, мне нужно использовать другой подход.

Может ли кто-нибудь помочь мне решить эту проблему?

1 Ответ

5 голосов
/ 15 апреля 2020
@ scala.math.pow(2, 63)
res0: Double = 9.223372036854776E18

Вы получаете Double на math.pow, а затем передаете результат в BigDecimal - это означает, что вы потеряли точность даже до того, как начали использовать Big* классы.

Если вы помещаете числа в BigDecimal, когда они еще маленькие и еще не потеряли точность (и если вы правильно используете конструкторы), тогда вы получите ожидаемый результат:

@ 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)
...