Search code examples
javascalabigdecimal

Scala 2.10 seems to lose precision in BigDecimal


The following test passes in Scala 2.11 and 2.12 but fails as shown for 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)

See the debugger output below, the breakpoint was on the test assertion

Debugger Screenshot

Is BigDecimal precision a known issue in Scala 2.10?


Solution

  • This is caused by the default MathContext in use. Scala 2.10 is using a MathContext with a precision of 34 characters, Scala 2.11 seems to be using one with a precision of 40 characters. To solve this I can specify the MathContext to use unlimited precision so changing the test as follows passes for all scala versions

    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)
      }
    
    }