2

我正在尝试用 Java 渲染一个名为“Lorenz Attractor”的分形。因为double不起作用(值超出范围),我决定选择 BigDecimals。经过 38 次迭代后,我的代码崩溃了,它给了我一个 ArithmeticException(下溢)。继承人的一些代码:

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("----------");

这是我得到的输出。我可以对此做些什么吗?抱歉,如果代码看起来不太好。我还可以提供一些关于应该如何完成的伪代码,告诉我你是否需要。

编辑:这是拆分的第二行:

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
4

1 回答 1

3

虽然BigDecimaldouble它仍然有限制更强大和灵活;即scale是一个int

BigDecimal 由一个任意精度的整数未缩放值和一个 32 位整数刻度组成。

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

那么,如果您遇到上溢或下溢错误,这意味着什么?您正在使用的数字的规模如此可笑地大或小,以至于BigDecimal无法支持它们。这几乎肯定意味着您犯了某种逻辑错误,并且没有执行您想要的操作 - 仔细检查您的数学。

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

于 2016-11-11T20:57:48.243 回答