Проблема с точностью BigDecimal?

Я пишу программу, в которой мне нужно многократно умножать два BigDecimal.

После 27-й итерации я получаю:

0.905225895893387921845435055445776361046057346344145563957027726

Любые дальнейшие вычисления с использованием этого числа (BigDecimal * 0.182365681285) приводят к появлению нулей в конце. Итак, следующая итерация возвращает: 0.905225895893387921845435055445776361046057346344145563957027726000000000000

Итерация после этого возвращает: 0.905225895893387921845435055445776361046057346344145563957027726000000000000000000000000

так далее..


Поэтому мне было интересно, было ли это связано с какой-то проблемой точности с BigDecimal.

Любая помощь приветствуется

Изменить: меня попросили опубликовать мой код. Я мог бы скопировать и вставить несколько страниц, которые у меня есть, но это очень точное представление того, что у меня есть на данный момент:

BigDecimal range = new BigDecimal(0.0012440624293146346);
for(int i = 0; i < 50 ; i++){
    low = low.multiply(range);
}

person John McBrown    schedule 16.03.2013    source источник
comment
Можете ли вы опубликовать свой полный код, чтобы люди могли видеть, что происходит?   -  person Jonathan Hedley    schedule 17.03.2013
comment
Вы не должны использовать конструктор double (двойникам не хватает точности) - вместо этого используйте конструктор String.   -  person assylias    schedule 17.03.2013


Ответы (2)


Метод умножения создает BigDecimal, масштаб которого равен масштабу первого операнда + масштабу второго операнда, даже если это приводит к замыкающим нулям. Чтобы убрать конечные нули, используйте... stripTrailingZeros().

person JB Nizet    schedule 16.03.2013
comment
Я попытался удалить конечные нули, но это не тот результат, которого я пытаюсь достичь, я просто получаю одно и то же число между 27-й и 50-й итерацией, что не имеет смысла. - person John McBrown; 17.03.2013
comment
@JohnMcBrown Вы правы, это не так. Можете ли вы предоставить код, который воспроизводит эту проблему? - person Peter Lawrey; 17.03.2013
comment
Я должен извиниться, но мне пришлось бы связать сотни файлов. Я ценю все советы, которые я получил до сих пор, и я обязательно повыслю их. Приятно знать, что у меня нет проблем с BigDecimal. - person John McBrown; 17.03.2013
comment
@JohnMcBrown Смысл этого ответа в том, что если вы хотите большей точности, вы должны увеличить точность операндов. Исходный операнд даже не имеет той точности, которую он имеет, потому что этот литерал уже усечен компилятором. Предоставьте его как строку, а не числовой литерал, и, при необходимости, отрегулируйте точность BigDecimal. - person user207421; 17.03.2013

Я обнаружил ситуацию, когда имитирует конечные нули.

BigDecimal bd = BigDecimal.valueOf(0.5);
BigDecimal a = BigDecimal.valueOf(1 << 20).divide(BigDecimal.valueOf(1000000));
for (int i = 0; i < 20; i++) {
    System.out.println(a);
    a = a.multiply(bd);
}

Примечание. BigDecimal не предполагает, что вы хотите удалить нули в конце по умолчанию.

1.048576
0.5242880
0.26214400
0.131072000
0.0655360000
0.03276800000
0.016384000000
0.0081920000000
0.00409600000000
0.002048000000000
0.0010240000000000
0.00051200000000000
0.000256000000000000
0.0001280000000000000
0.00006400000000000000
0.000032000000000000000
0.0000160000000000000000
0.00000800000000000000000
0.000004000000000000000000
0.0000020000000000000000000

Нет причин, по которым вы должны получать нули, которых не должно быть, если вы каждый раз не умножаете двойные значения, преобразованные в BigDecimal.

person Peter Lawrey    schedule 16.03.2013
comment
В описанной вами ситуации я могу убрать конечные нули и получить точное число. В моей ситуации я получаю одно и то же число на каждой итерации после 27-го числа. Удаление конечных нулей приводит к точно такому же числу. я не могу понять почему - person John McBrown; 17.03.2013
comment
Вам нужно записать значения, которые вы умножили, и результат, который вы получили. Таким образом, вы сможете воспроизвести расчет одной строкой. Какую версию Java вы используете? Если у вас старая версия Java 5.0, это может быть ошибкой. - person Peter Lawrey; 17.03.2013