На данный вопрос уже ответили:
Есть простейший код:
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 и дальше ближе к максимальному значению - все больше погрешность. В чем дело?
Дело в типах double и float. В вычислениях, связанных с ними, практически всегда есть погрешности в вычислениях, связанные с округлением. Если хотите точности в таких числах, используйте BigDecimal.
У 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;
то точность ещё больше возрастёт.
Это фундаментальная проблема. 0.1 (как и большинство других дробных чисел) невозможно точно записать в двоичной системе, всегда будет погрешность. Чем больше разрядность (процессора), тем погрешность меньше, но она будет всегда. И чем больше вычислений накладываются друг на друга, тем больше отличия "компьютерного" результата от математического.
Отсюда следует, что нельзя сравнивать два float или double, полученных в результате вычислений, с помощью оператора ==
. Обычно определяют максимально допустимую погрешность epsilon
и затем вычисляют, попадает ли разница между двумя числами в эту погрешность:
float epsilon = 0.00000001;
float diff = f1 - f2;
if (diff < epsilon && diff > -epsilon){
// здесь код
}
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
ситуация вот какая: есть таблица в бд Postgresql,в ней есть поле "статус"Требуется выполнить некий кусок Java-кода, при любом изменении статуса
Есть два потока, которые обращаются к одному классу, который делает запрос в БДМне необходимо сделать так, что бы они физически не могли сделать...
Как правильно реализовать анимацию градиента SVG элемента под углом и с задержкой?