Как разрешить, что Java, Округляющийся Дважды, выходит [копируют]

Попробуйте выполнить следующую команду:

n = line number
tail -r file_name | sed '1,nd' | tail -r
74
задан Michael Myers 30 April 2009 в 20:49
поделиться

9 ответов

Для управления точностью арифметики с плавающей точкой необходимо использовать java.math. BigDecimal. Читайте потребность в BigDecimal John Zukowski для получения дополнительной информации.

, Учитывая Ваш пример, последняя строка как следовала бы за использованием BigDecimal.

import java.math.BigDecimal;

BigDecimal premium = BigDecimal.valueOf("1586.6");
BigDecimal netToCompany = BigDecimal.valueOf("708.75");
BigDecimal commission = premium.subtract(netToCompany);
System.out.println(commission + " = " + premium + " - " + netToCompany);

Это приводит к следующему выводу.

877.85 = 1586.6 - 708.75
94
ответ дан LordOfThePigs 24 November 2019 в 11:51
поделиться

Как предыдущие указанные ответы, это - последствие выполнения арифметики с плавающей точкой.

Как предыдущий предложенный плакат, Когда Вы делаете числовые вычисления, использование java.math.BigDecimal.

Однако существует глюк к использованию BigDecimal. Когда Вы преобразовываете от двойного значения до BigDecimal, у Вас есть выбор использования нового BigDecimal(double) конструктор или BigDecimal.valueOf(double) статический метод фабрики. Используйте статический метод фабрики.

двойной конструктор преобразовывает всю точность double к BigDecimal, в то время как статическая фабрика эффективно преобразовывает ее в String, затем преобразовывает это в BigDecimal.

Это становится релевантным при столкновении с теми тонкими погрешностями округления. Число могло бы отобразиться как.585, но внутренне его значение '0.58499999999999996447286321199499070644378662109375'. Если бы Вы использовали BigDecimal конструктор, Вы получили бы число, которое не равно 0,585, в то время как статический метод дал бы Вам значение, равное 0,585.

double value = 0.585;
System.out.println(new BigDecimal(value));
System.out.println(BigDecimal.valueOf(value));

в моей системе дает

0.58499999999999996447286321199499070644378662109375
0.585
65
ответ дан Alex 24 November 2019 в 11:51
поделиться

Другой пример:

double d = 0;
for (int i = 1; i <= 10; i++) {
    d += 0.1;
}
System.out.println(d);    // prints 0.9999999999999999 not 1.0

Использование BigDecimal вместо этого.

РЕДАКТИРОВАНИЕ:

кроме того, только для указания это не проблема округления 'Java'. Другие языки показывают подобный (хотя не обязательно последовательный) поведение. Java, по крайней мере, гарантирует последовательное поведение в этом отношении.

10
ответ дан toolkit 24 November 2019 в 11:51
поделиться

Любое время, с которым Вы делаете вычисления, удваивается, это может произойти. Этот код дал бы Вам 877.85:

двойной ответ = Math.round (dCommission * 100000) / 100000.0;

7
ответ дан Steve Klabnik 24 November 2019 в 11:51
поделиться

Сохраните количество центов, а не долларов, и просто сделайте формат к долларам при выводе его. Тем путем можно использовать целое число, которое не страдает от проблем точности.

4
ответ дан tloach 24 November 2019 в 11:51
поделиться

Посмотрите ответы на этот вопрос . По существу то, что Вы видите, является естественным следствием использования арифметики с плавающей точкой.

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

3
ответ дан Community 24 November 2019 в 11:51
поделиться

Я бы изменил приведенный выше пример следующим образом:

import java.math.BigDecimal;

BigDecimal premium = new BigDecimal("1586.6");
BigDecimal netToCompany = new BigDecimal("708.75");
BigDecimal commission = premium.subtract(netToCompany);
System.out.println(commission + " = " + premium + " - " + netToCompany);

Таким образом, вы избежите ловушек использования строки для начала. Другая альтернатива:

import java.math.BigDecimal;

BigDecimal premium = BigDecimal.valueOf(158660, 2);
BigDecimal netToCompany = BigDecimal.valueOf(70875, 2);
BigDecimal commission = premium.subtract(netToCompany);
System.out.println(commission + " = " + premium + " - " + netToCompany);

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

8
ответ дан 24 November 2019 в 11:51
поделиться

Самый элегантный и эффективный способ сделать это на Java:

double newNum = Math.floor(num * 100 + 0.5) / 100;
2
ответ дан 24 November 2019 в 11:51
поделиться
double rounded = Math.rint(toround * 100) / 100;
1
ответ дан 24 November 2019 в 11:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: