Исправлена ошибка точности поплавка без BigDecimal
У меня проблема с округлением значения с плавающей запятой.
Следующий код дает мне следующий результат:
public class ProductOrder {
public static void main(String[] args) {
int q = 48;
float p = 6.95f;
System.out.println(q * p);
}
------
Output: 333.59998
Пока ожидаемый результат должен быть 333,6
Когда я заменяю q на 49, тогда все в порядке, и я получаю 340,55
4 ответа
Как уже указывалось, BigDecimal разработан для ситуаций, в которых точная обработка коротких десятичных дробей особенно важна, и намного лучше для этих ситуаций, чем любой двоичный формат с плавающей запятой.
Второе лучшее решение - это, например, работать с целым числом центов и вставлять десятичную точку только во время отображения.
Если вы должны использовать двоичную с плавающей запятой, обычно лучше использовать double, чем float, если только вы не имеете дело с большим числом чисел и знаете, что у float достаточно точности.
Для вывода, если вы ожидаете результат с, например, не более 2 десятичными цифрами после десятичной точки, вы можете использовать DecimalFormat для округления соответственно:
import java.text.DecimalFormat;
public class Test {
public static void main(String[] args) {
DecimalFormat df = new DecimalFormat("#0.##");
int q = 48;
float p = 6.95f;
System.out.println(df.format(q * p));
}
}
печатает 333.6
Форматирование по умолчанию производит наименьшее количество цифр, которое необходимо, чтобы отличить число от соседей. Это означает, что если результат даже слегка отклонен из-за ошибки округления, вы получите "некрасивый" вывод.
Один из способов справиться с этим - использовать точную арифметику (BigDecimal или целочисленную арифметику). Другой округляет вывод, например:
System.out.printf("%f", p*q);
Число 333.6
не представляется точно так же, как float
, который имеет точность до 6 десятичных цифр. Когда вы пытались напечатать его с слишком большой точностью (8 цифр), была обнаружена основная ошибка округления.
double
имеет точность до 15 цифр.
Однако, как отмечали другие, если вы имеете дело с финансовыми расчетами, вы должны работать в BigDecimal
,
Для справки вы можете использовать веб-сайт IEEE-754 для преобразования с плавающей запятой, чтобы увидеть, для любого заданного десятичного числа, как именно оно представлено в float
а также double
,
Проблема здесь заключается в том, что числа с плавающей запятой подвержены ошибкам точности с плавающей запятой. Ты можешь использовать double
для удвоения точности (вы все равно в конечном итоге получите ошибки, но это более точно, чем использование float
).
Например
public static void main(String[] args) {
int q = 48;
double p = 6.95;
System.out.println(q * p);
}