2014-01-25 3 views
4

Я перепутал с результатом выполнения кода.удивительное двойное сравнение

код:

System.out.println(0.2==0.1+0.1); 
System.out.println(0.3==0.1+0.1+0.1); 

выход:

true 
false 

Я знаю, что 0,2 и 0,3 не может преобразовать в двоичную правильно.

Почему я вижу разные результаты?

UPDATE:

Могу ли я предсказать результат в подобных вопросах без компилятора?

+0

также справедлив для '' C++. – herohuyongtao

+1

php тот же результат! –

+0

Я не знаю javascript – gstackoverflow

ответ

0

PHP дал это:

<?php 

printf("%0.20f\n", 0.1+0.1); 
printf("%0.20f\n", 0.1+0.1+0.1); 

?> 
0.20000000000000001110 
0.30000000000000004441 

и

<?php 
    echo 0.2==0.1+0.1?"true\n":"false\n"; 
    echo 0.3==0.1+0.1+0.1?"true\n":"false\n"; 
?> 
true 
false 

reaseon для первого быть "истинным":

<?php 
    printf("%0.20f\n", 0.1+0.1); 
    printf("%0.20f\n", 0.1+0.1+0.1); 
    echo "\n"; 
    printf("%0.20f\n", 0.2); 
    printf("%0.20f\n", 0.3); 
?> 

Выход

0.20000000000000001110 
0.30000000000000004441 

0.20000000000000001110 
0.29999999999999998890 
+0

nr4bt объяснил, почему * System.out.println (0.3 == 0.1 + 0.1 + 0.1) * возвращает false. но я не отвечаю, почему * System.out.println (0.2 == 0.1 + 0.1) * return true – gstackoverflow

+0

По вашим результатам - очень странно – gstackoverflow

+0

о вашем обновлении: могу ли я предсказать результат без компилятора? – gstackoverflow

9
System.out.println(0.1+0.1+0.1); 

выход

0.30000000000000004 

Существует ошибка округления по точечным арифметике с плавающей. Некоторые значения не могут быть представлены в базе 2, вы не можете полагаться на сравнение чисел с плавающей запятой. 0,1 в основании-2 составляет 1/3 в основании-10.

Вы можете увидеть ссылку

What Every Computer Scientist Should Know About Floating-Point Arithmetic

+0

Я собирался добавить комментарий, что это было возможно. – Hosch250

+2

Зачем нормально для '0.1 + 0.1'? – herohuyongtao

+0

Каждый раз, когда вы выполняете дополнительный расчет с поплавками, вы получаете все больше и больше ошибок в ответе. Когда вы добавили только 2 поплавки, ошибка была недостаточно большой, чтобы ее можно было рассмотреть! =. – csmckelvey

2

То, что вы видите, тот факт, что значения с плавающей точкой не очень точны, и вы не должны, например, сравнить их с помощью == оператора. Для сравнения вы должны использовать epsilon, то есть. для двух значений с плавающей точкой f1 и f2

if (Math.abs(f1 - f2) < EPSILON) { 
    // they are equal 
} 

Где Эпсилон некоторые очень маленькие значения с плавающей точкой

+0

... Где EPSILON - это очень маленькое значение с плавающей запятой _отклонение необходимой точности в сравнении, но не менее этого –

0

Вы не можете полагаться на == хорошо работать для float чисел, результаты которых ненадежны, потому что они не могут быть представлены точно на компьютерах. Если вы хотите проверить два одинаковых числа float, используйте вместо этого fabs(a-b) < epsilon.

P.S. Следующий тест находится под C++, что дает удивительные результаты (просто для удовольствия, чтобы показать, как не-надежно это):

cout << (0.1==0.1) << endl;        // true 
cout << (0.2==0.1+0.1) << endl;       // true 
cout << (0.3==0.1+0.1+0.1) << endl;      // false 
cout << (0.4==0.1+0.1+0.1+0.1) << endl;     // true 
cout << (0.5==0.1+0.1+0.1+0.1+0.1) << endl;    // true 
cout << (0.6==0.1+0.1+0.1+0.1+0.1+0.1) << endl;   // true 
cout << (0.7==0.1+0.1+0.1+0.1+0.1+0.1+0.1) << endl;  // true   
cout << (0.8==0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1) << endl; // false 

 Смежные вопросы

  • Нет связанных вопросов^_^