首页 > 解决方案 > Scala 2.10 似乎在 BigDecimal 中失去了精度

问题描述

以下测试在 Scala 2.11 和 2.12 中通过,但如 2.10 所示失败

class JsonToXmlParserTest extends Suite with Matchers with AssertionsForJUnit {
  @Test
  def testBigDecimalPrecision(): Unit = {
    val decimalString = "12345678901234567890.12345678901234567890"
    val bigDecimal = BigDecimal(decimalString)
    val javaBigDecimal = new java.math.BigDecimal(decimalString)

    javaBigDecimal.compareTo(bigDecimal.bigDecimal) should be(0)
  }

}
org.scalatest.exceptions.TestFailedException: -1 was not equal to 0
    at org.scalatest.MatchersHelper$.indicateFailure(MatchersHelper.scala:346)
    at org.scalatest.Matchers$ShouldMethodHelper$.shouldMatcher(Matchers.scala:6668)
    at org.scalatest.Matchers$AnyShouldWrapper.should(Matchers.scala:6704)

请参阅下面的调试器输出,断点位于测试断言上

调试器截图

精度是BigDecimalScala 2.10 中的一个已知问题吗?

标签: javascalabigdecimal

解决方案


这是由MathContext使用中的默认值引起的。Scala 2.10 使用的MathContext是精度为 34 个字符的 a,Scala 2.11 似乎使用的是精度为 40 个字符的。为了解决这个问题,我可以指定MathContext使用无限精度,因此更改测试如下通过所有 scala 版本

class JsonToXmlParserTest extends Suite with Matchers with AssertionsForJUnit {
  @Test
  def testBigDecimalPrecision(): Unit = {
    val decimalString = "12345678901234567890.12345678901234567890"
    val bigDecimal = BigDecimal(decimalString, MathContext.UNLIMITED)
    val javaBigDecimal = new java.math.BigDecimal(decimalString, MathContext.UNLIMITED)

    javaBigDecimal.compareTo(bigDecimal.bigDecimal) should be(0)
  }

}

推荐阅读