BigDecimal Underflow

Я пытаюсь визуализировать фрактал под названием "Аттрактор Лоренца" с помощью 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("----------");

Это вывод, который я получаю. Могу ли я что-нибудь сделать против этого? Извините, если код не выглядит очень хорошо. Я также могу предоставить некоторый псевдокод о том, как это должно быть сделано, скажите мне, если вам это нужно.

РЕДАКТИРОВАТЬ: Это вторая строка разделена:

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 ответ

В то время как BigDecimal гораздо более мощный и гибкий, чем double у этого все еще есть пределы; а именно его scale является int:

BigDecimal состоит из целочисленного немасштабированного значения произвольной точности и 32-битной целочисленной шкалы.

Это означает, что вы не можете представлять числа, большие или меньшие, чем масштабированные с коэффициентом более 2^31. Это огромное (или крошечное) число (10^2^31 - максимально возможный множитель), и для почти любого возможного варианта использования это непрактичный крайний случай. Для сравнения, во вселенной "только" примерно 4×10^80 атомов.

Так что это значит, если вы сталкиваетесь с ошибками переполнения или недополнения? Масштаб чисел, с которыми вы работаете, настолько смехотворно велик или мал, что BigDecimal не могу их поддержать. Это почти наверняка означает, что вы допустили какую-то логическую ошибку и не выполняете операций, для которых вы намеревались - перепроверить свою математику.

Иногда проблема заключается в порядке операций - например, ваш результат может быть достаточно небольшим, но промежуточные шаги неосуществимы. Вычисление биномиального коэффициента является примером этого. В таких случаях вам нужно экспериментировать с другими порядками работы, которые позволяют избежать таких необоснованных цифр.

Другие вопросы по тегам