BigDecimal下溢

时间:2015-04-30 12:49:03

标签: java bigdecimal arithmeticexception

我正试图渲染一个名为" Lorenz Attractor"用Java。因为double不起作用(值超出范围),所以我决定选择BigDecimals。经过38次迭代后,我的代码崩溃,它让我得到一个ArithmeticException(Underflow)。下面是一些代码:

BigDecimal xnew = this.x.add(this.hBig.multiply(BigDecimal.TEN).multiply(this.x.add(this.y.negate())));

//This is the line that crashes
BigDecimal ynew = this.y.add(this.hBig.multiply(this.x.negate().multiply(this.z)).add(ZWENTYEIGHT.multiply(this.x.add(this.y.negate()))));

BigDecimal znew = this.z.add(this.hBig.multiply(this.x.multiply(this.y).add(FRAC.multiply(this.z).negate())));

this.x = xnew;
this.y = ynew;
this.z = znew;
System.out.println("X="+this.x);
System.out.println("Y="+this.y);
System.out.println("Z="+this.z);
System.out.println("----------");

This is the output I get。 我能反对吗?对不起,如果代码看起来不是很好。我还可以提供一些伪代码,告诉我你是否需要它。

编辑:这是第二行拆分:

BigDecimal temp = ZWENTYEIGHT.multiply(this.x.add(this.y.negate()));
BigDecimal temp2 = this.x.negate().multiply(this.z);
BigDecimal temp3 = this.hBig.multiply(temp2); //This crashes.
BigDecimal temp4 = temp3.add(temp);
BigDecimal ynew = this.y.add(temp4);

EDIT2:这是一些伪代码:

do 4000 times
    xnew=x+h*10*(x-y)
    ynew=y+h*((-x*z)+28*x-y)
    znew=z+h*(x*y-8/3*z)
    x=xnew
    y=ynew
    z=znew

1 个答案:

答案 0 :(得分:3)

虽然BigDecimaldouble强大且灵活,但仍然有限制;即its scale is an int

  

BigDecimal由任意精度整数非标度值和32位整数标度组成。

这意味着您不能表示大于或小于按比例大于2 ^ 31的数字的数字。这是一个大量的(或微小的)数字(10 ^ 2 ^ 31是最大可能的乘数),对于几乎任何可能的用例来说,这是一个不切实际的边缘情况。相比之下,宇宙中“仅”约有4×10 ^ 80个原子。

那么,如果您遇到Overflow或Underflow错误,这意味着什么?您正在使用的数字的大小非常大或小,BigDecimal无法支持它们。这完全肯定意味着你已经犯了某种逻辑错误,而且没有做你想要的操作 - 仔细检查你的数学。

偶尔问题是操作的顺序 - 例如您的结果可能是一个合理大小的数字,但中间步骤是不可行的。计算binomial coefficient就是一个例子。在这种情况下,您需要尝试避免此类不合理数字的其他操作顺序。