Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BigDecimal precision explosion

I'm trying to do calculations in Scala (and/or Java) at a fixed precision larger than that of a double. I'm using BigDecimals with Scala's default MathContext, which has precision 34. Even though all the inputs have this precision, I'm finding that after a few computations, the precision of the results starts to explode.

Here's an example computation that I think illustrates the problem:

import math.BigDecimal

val z40 = BigDecimal(0).setScale(40) // 0E-40
z40.scale                            // 40
z40.precision                        // 1
(1 + z40*z40).precision              // 81

the result is 81, which is higher precision than z40. In my case, I'm never using setScale, but zeros with very large scales are arising in computations.

This is not the behavior I want. I would like (1 + z40*z40) to have precision 34 -- the precision of the MathContext in which the computations are being performed (since z40*z40 is negligibly small compared to 1). How can I get this kind of arithmetic?

Update: This behavior is due to a change in the handling of MathContexts between Scala 2.9.* and 2.10.*. (Thanks to Paul Phillips for pointing out the commit.) See also this discussion.

like image 768
davidsd Avatar asked Oct 22 '22 20:10

davidsd


1 Answers

Seems strange. I tried your code and get the result as you expected:

$ scala
Welcome to Scala version 2.9.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_10).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import math.BigDecimal
import math.BigDecimal

scala> val z40 = BigDecimal(0).setScale(40)
z40: scala.math.BigDecimal = 0E-40

scala> z40.scale
res0: Int = 40

scala> z40.precision
res1: Int = 1

scala> (1 + z40*z40).precision
res2: Int = 34

scala> _

As you can see, (1+z40*z40).precision is 34 as you expected.

like image 119
ntalbs Avatar answered Oct 24 '22 17:10

ntalbs