2

「ローレンツ アトラクタ」と呼ばれるフラクタルを 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("----------");

これは私が得る出力です。それに対して何かできることはありますか?コードが見栄えがよくない場合は申し訳ありません。また、それをどのように行うべきかについての疑似コードを提供することもできます。必要な場合は教えてください。

編集:これは分割された2番目の行です:

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

まだ制限があるBigDecimalよりもはるかに強力で柔軟ですが。doubleつまり、次scaleintとおりです。

BigDecimal は、スケーリングされていない任意精度の整数値と 32 ビットの整数スケールで構成されます。

これは、2^31 を超える係数でスケーリングされた数値よりも大きいまたは小さい数値を表すことができないことを意味します。これは非常に大きな(または非常に小さい) 数値であり (10^2^31 が可能な最大の乗数)、ほぼすべての可能なユース ケースで遭遇するのは非現実的なエッジ ケースです。それに比べて、宇宙にはおよそ 4×10^80 個の原子しかありません。

では、オーバーフローまたはアンダーフロー エラーが発生した場合、それはどういう意味でしょうか? あなたが扱っている数字のスケールは、ばかげたほど大きくも小さくもなりすぎて、BigDecimalそれらをサポートできません。これは間違いなく、何らかの論理エラーが発生し、意図した操作を実行していないことを意味します。計算を再確認してください。

場合によっては、操作の順序に問題がある場合があります。たとえば、結果は適切なサイズの数値になる場合がありますが、中間の手順は実行できません。二項係数の計算は、この例です。このような場合、そのような不合理な数を避けるために、他の操作順序を試してみる必要があります。

于 2016-11-11T20:57:48.243 に答える