BigDecimal.add 奇怪的行为
BigDecimal.add strange behavior
方法BigDecimal.add
当一个参数的指数很大(9 位),而第二个参数的指数长度不同时,需要很长时间。已经等了5分多钟了,还在一直等
代码如下:
@Test
public void testAddBig() throws Exception {
MathContext mc = new MathContext(10, RoundingMode.HALF_UP);
BigDecimal v1 = new BigDecimal("1E+100000000", mc);
BigDecimal v2 = new BigDecimal("1", mc);
System.out.println(v1.add(v2));
}
这是线程转储的一部分:
at java.math.BigInteger.square(BigInteger.java:1884)
at java.math.BigInteger.squareKaratsuba(BigInteger.java:1975)
at java.math.BigInteger.square(BigInteger.java:1888)
at java.math.BigInteger.squareToomCook3(BigInteger.java:2011)
at java.math.BigInteger.square(BigInteger.java:1890)
at java.math.BigInteger.squareToomCook3(BigInteger.java:2006)
at java.math.BigInteger.square(BigInteger.java:1890)
at java.math.BigInteger.squareToomCook3(BigInteger.java:2012)
at java.math.BigInteger.square(BigInteger.java:1890)
at java.math.BigInteger.squareToomCook3(BigInteger.java:2010)
at java.math.BigInteger.square(BigInteger.java:1890)
at java.math.BigInteger.squareToomCook3(BigInteger.java:2006)
at java.math.BigInteger.square(BigInteger.java:1890)
at java.math.BigInteger.squareToomCook3(BigInteger.java:2012)
at java.math.BigInteger.square(BigInteger.java:1890)
at java.math.BigInteger.squareToomCook3(BigInteger.java:2011)
at java.math.BigInteger.square(BigInteger.java:1890)
at java.math.BigInteger.pow(BigInteger.java:2263)
at java.math.BigDecimal.bigTenToThe(BigDecimal.java:3543)
at java.math.BigDecimal.bigMultiplyPowerTen(BigDecimal.java:4508)
at java.math.BigDecimal.add(BigDecimal.java:4443)
at java.math.BigDecimal.add(BigDecimal.java:1289)
这是怎么回事?这是一个错误吗?
嗯,简单回答一下。 BigNumbers 使用字符数组来保持最大精度。由于您的号码将由 100000000 位数字组成,因此这将是您的数组的长度。
100.000.000 chars = bytes
如果我没记错的话,这是100MB。然后你想用它做数学,这开始需要大量阅读 ;)
如果你打开 BigDecimal class,你会看到有很多检查,因为这是 "letter" 而不是数字。
BigDecimal 有助于保持精度,但这样做需要付出一定的代价,这里是内存和处理时间。
编辑:
如果您以某些方式使用实例,这只会是一个问题,构造函数会将值存储为指数值 1E+***。如果你打印它,这会很好,但如果你问一个数值,这将开始失败。
更准确地说,BigDecimal.bigTenToThe(int)
将收到指数值 (1000000000)。
private static BigInteger bigTenToThe(int n) {
...
char tenpow[] = new char[n + 1];
....
}
方法BigDecimal.add
当一个参数的指数很大(9 位),而第二个参数的指数长度不同时,需要很长时间。已经等了5分多钟了,还在一直等
代码如下:
@Test
public void testAddBig() throws Exception {
MathContext mc = new MathContext(10, RoundingMode.HALF_UP);
BigDecimal v1 = new BigDecimal("1E+100000000", mc);
BigDecimal v2 = new BigDecimal("1", mc);
System.out.println(v1.add(v2));
}
这是线程转储的一部分:
at java.math.BigInteger.square(BigInteger.java:1884)
at java.math.BigInteger.squareKaratsuba(BigInteger.java:1975)
at java.math.BigInteger.square(BigInteger.java:1888)
at java.math.BigInteger.squareToomCook3(BigInteger.java:2011)
at java.math.BigInteger.square(BigInteger.java:1890)
at java.math.BigInteger.squareToomCook3(BigInteger.java:2006)
at java.math.BigInteger.square(BigInteger.java:1890)
at java.math.BigInteger.squareToomCook3(BigInteger.java:2012)
at java.math.BigInteger.square(BigInteger.java:1890)
at java.math.BigInteger.squareToomCook3(BigInteger.java:2010)
at java.math.BigInteger.square(BigInteger.java:1890)
at java.math.BigInteger.squareToomCook3(BigInteger.java:2006)
at java.math.BigInteger.square(BigInteger.java:1890)
at java.math.BigInteger.squareToomCook3(BigInteger.java:2012)
at java.math.BigInteger.square(BigInteger.java:1890)
at java.math.BigInteger.squareToomCook3(BigInteger.java:2011)
at java.math.BigInteger.square(BigInteger.java:1890)
at java.math.BigInteger.pow(BigInteger.java:2263)
at java.math.BigDecimal.bigTenToThe(BigDecimal.java:3543)
at java.math.BigDecimal.bigMultiplyPowerTen(BigDecimal.java:4508)
at java.math.BigDecimal.add(BigDecimal.java:4443)
at java.math.BigDecimal.add(BigDecimal.java:1289)
这是怎么回事?这是一个错误吗?
嗯,简单回答一下。 BigNumbers 使用字符数组来保持最大精度。由于您的号码将由 100000000 位数字组成,因此这将是您的数组的长度。
100.000.000 chars = bytes
如果我没记错的话,这是100MB。然后你想用它做数学,这开始需要大量阅读 ;)
如果你打开 BigDecimal class,你会看到有很多检查,因为这是 "letter" 而不是数字。
BigDecimal 有助于保持精度,但这样做需要付出一定的代价,这里是内存和处理时间。
编辑:
如果您以某些方式使用实例,这只会是一个问题,构造函数会将值存储为指数值 1E+***。如果你打印它,这会很好,但如果你问一个数值,这将开始失败。
更准确地说,BigDecimal.bigTenToThe(int)
将收到指数值 (1000000000)。
private static BigInteger bigTenToThe(int n) {
...
char tenpow[] = new char[n + 1];
....
}