#java #float
This question already has answers here:
Вычисления на числах с плавающей точкой не работают
(2 ответа)
Закрыт 1 год назад.
Есть простейший код:
private static float val = 0f;
public static void main(String[] args) {
for (int i = 0; i < 100000; i++ ) {
val = val + 0.1f;
System.out.println(val);
}
}
Ожидаю в конце получить 100000*0,1 = 10000. Но последнее значение: 9998.557.
Если запустите код - увидите, что значения отображаются неточно, должны быть четко
с шагом 0,1 но вместо 0,8 - 0.8000001, вместо 2000 - 2000.0587 и дальше ближе к максимальному
значению - все больше погрешность. В чем дело?
Ответы
Ответ 1
Дело в типах double и float. В вычислениях, связанных с ними, практически всегда есть погрешности в вычислениях, связанные с округлением. Если хотите точности в таких числах, используйте BigDecimal.Ответ 2
У Float типа точность гораздо ниже чем у Double. Если для вас критичен результат, то используйте Double. Простейший пример демонстрирующий погрешность: public static void main(String[] args) { double dob = 0.1f; float flo = 0.1f; System.out.println("Float: " + flo); System.out.println("Double: " + dob); } Результат: Float: 0.1 Double: 0.10000000149011612 В вашем коде если тип переменной изменить на Double, то получится то что вы ожидали от кода: private static double val = .0; public static void main(String[] args) { for (int i = 0; i < 100000; i++ ) { val = val + 0.1f; System.out.println(val); } } Результат: 9999.700149007142 9999.800149008632 9999.900149010122 10000.000149011612 А если инкремент val = val + 0.1f; сменить на val = val + 0.1; то точность ещё больше возрастёт.Ответ 3
Это фундаментальная проблема. 0.1 (как и большинство других дробных чисел) невозможно точно записать в двоичной системе, всегда будет погрешность. Чем больше разрядность (процессора), тем погрешность меньше, но она будет всегда. И чем больше вычислений накладываются друг на друга, тем больше отличия "компьютерного" результата от математического. Отсюда следует, что нельзя сравнивать два float или double, полученных в результате вычислений, с помощью оператора ==. Обычно определяют максимально допустимую погрешность epsilon и затем вычисляют, попадает ли разница между двумя числами в эту погрешность: float epsilon = 0.00000001; float diff = f1 - f2; if (diff < epsilon && diff > -epsilon){ // здесь код }
Комментариев нет:
Отправить комментарий