问题
I am trying to render a fractal called the "Lorenz Attractor" with Java. Because double
does not work (values out of range), I decided to choose BigDecimals. After 38 iterations my code crashes, it gets me an ArithmeticException (Underflow). Heres some of the code:
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. Can I do anything against that? Sorry if the code doesn't look very good. I can also provide some pseudocode on how it should be done, tell me if you need that.
EDIT: This is the second line split up:
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: This is some pseudocode:
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:
While BigDecimal
is much more powerful and flexible than double
it does still have limits; namely its scale is an int:
A BigDecimal consists of an arbitrary precision integer unscaled value and a 32-bit integer scale.
This means that you cannot represent numbers larger or smaller than are scaled by a factor of more than 2^31. This is a massive (or minuscule) number (10^2^31 being the largest possible multiplier), and for almost any possible use case it's an impractical edge case to run into. By comparison there are "only" approximately 4×10^80 atoms in the universe.
So what does it mean if you're running into Overflow or Underflow errors? The scale of the numbers you're working with are so ludicrously large or small that BigDecimal
can't support them. This all-but-certainly means you've made a logic error of some sort, and are aren't doing the operations you intended to - double-check your math.
Occasionally the problem is the order of operations - e.g. your result might be a reasonably sized number, but the intermediary steps are unworkable. Computing the binomial coefficient is an example of this. In such cases you need to experiment with other orders of operation that avoid such unreasonable numbers.
来源:https://stackoverflow.com/questions/29968205/bigdecimal-underflow