2013-09-19 5 views
9

Я смущен о поведении числа с плавающей запятой после просмотра результата следующего фрагмента кода.float и double confusion

float var1 = 5.4f; 
    float var2 = 5.5f; 

    if(var1 == 5.4) 
     System.out.println("Matched"); 
    else 
     System.out.println("Oops!!"); 

    if(var2 == 5.5) 
     System.out.println("Matched"); 
    else 
     System.out.println("Oops!!"); 

Выход:

Oops!! 
Matched 

Является ли это из-за десятичного числа, которые не могут быть точно представлять в базовом 2 двоичном формате? OR Это из-за точности, когда я сравниваю переменную типа float с двойным типом? Если да, то почему он работает отлично для следующей переменной?

+0

Много информации, просто google вокруг :) Во-первых, используйте double over float, а также см. 'BigDecimal' ... – vikingsteve

+0

Возможный дубликат [Сравнение плавающих и двойных примитивов в Java] (http://stackoverflow.com/ вопросы/7392167/сравнение-float-and-double-primitives-in-java) – devnull

+0

В другом вопросе это очень хорошо обсуждается http://stackoverflow.com/questions/1088216/whats-wrong-with-using-to-compare-floats -in-java – AurA

ответ

16

Это из-за десятичного числа, которое не может быть точно представлено в двоичном формате базы 2?

Да. В принципе, 5.4f и 5.4dне то же самое, потому что ни одно из них не является точным представлением 5.4.

5.5f и 5.5dэто то же самое, поскольку они оба являются точными представлениями 5.5.

Обратите внимание, что 5.4 неявно совпадает с 5.4d - тип по умолчанию для литерала с плавающей запятой - double. Любое использование бинарного оператора с операндами float и double будет продвигать float до double и выполнять операцию над двумя значениями double.

Это может облегчить представление об этом в терминах десятичных чисел типов. Предположим, что у нас было два типа: Decimal5 и Decimal10, которые являются десятичными числами с 5 или 10 значащими цифрами. Тогда рассмотрит «третью» и «четверть»:

A third: 
Decimal5: 0.33333 
Decimal10: 0.3333333333 

A quarter (showing trailing zeroes just for clarity): 
Decimal5: 0.25000 
Decimal10: 0.2500000000 

При сравнении значения Decimal5 ближайших к третьему со значением Decimal10, значение Decimal5 будет преобразовано в значение Decimal10 из 0.3333300000, который не делает равным 0.3333333333. Это похоже на ваш первый пример.

При сравнении значений за квартал значение Decimal5 0,25000 преобразуется в 0.2500000000, что совпадает с значением Decimal10, которое у нас есть в течение четверти. Это похоже на ваш второй пример.

Конечно, бинарные типы с плавающей запятой немного сложнее, чем при нормализации, субнормальных числах и т. Д., Но для целей вашего примера эта аналогия достаточно близка.

+0

Спасибо, я понял. : D –

+0

Фактически, есть еще один момент, который не обсуждается. когда вы делаете if (var1 == 5.4), что действительно происходит? Похоже, что var1 неявно бросается в двойное и сравнивается с 5.4d. – thang

+0

@thang: Да. Я действительно обсуждал это по моей аналогии, показывая, что значение Decimal5 преобразуется в значение Decimal10. –

3

Замените, если состояние с:

if(var1 == 5.4f) 
    System.out.println("Matched"); 
else 
    System.out.println("Oops!!"); 

if(var2 == 5.5f) 
    System.out.println("Matched"); 
else 
    System.out.println("Oops!!"); 

Затем он напечатает Matched оба раза. Причина в том, что без квалификатора f в конце Java обрабатывает 5.4 как двойной, который не может быть представлен точно по сравнению с 5.5.

+0

Из вопроса ясно, что вопросник знает разницу между добавлением конечного «f» и его оставлением. Его вопрос заключался в том, что один из плавающих был равен его двойной счетной части, а другой - нет. @Jon Skeet ответил на это правильно. – Andromeda

2

Легко видеть:

if(var1 == 5.4f) 
    System.out.println("Matched"); 
else 
    System.out.println("Oops!!"); 

if(var2 == 5.5f) 
    System.out.println("Matched"); 
else 
    System.out.println("Oops!!"); 

Выход:

Matched 
Matched 

Двоичное представление 5.4f и 5.4d не точно такие же

+0

Педантичность: двоичное представление 5.5f и 5.5d также не совпадает (как в случае, если вы должны сравнивать память напрямую). То, что вы, вероятно, хотели сказать, состоит в том, что фактическое число, представленное двоичным представлением 5.4f и 5.4d, не совпадает. – thang

0

Если вы хотите сравнить типы с плавающей точкой, вы должны использовать сравнение с epsilon. Here вы можете увидеть все способы использования типов с плавающей запятой.

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