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];
    ....
}