Это потому, что ближайшее значение с плавающей запятой к 1,3 отличается от ближайшего двойного значения до 1,3. Ни одно из этих значений не будет точно 1,3, которое не может быть точно представлено в неповторяющемся двоичном представлении.
Чтобы по-разному понять, почему это происходит, предположим, что у нас было два десятичных типа с плавающей запятой - decimal5
и decimal10
, где число представляет количество значащих цифр. Теперь предположим, что мы попытались присвоить значение «треть» им обоим. Вы бы в конечном итоге с
decimal5 oneThird = 0.33333
decimal10 oneThird = 0.3333333333
Очевидно, что эти значения не равны. Здесь то же самое, только с разными базами.
Однако, если вы ограничите значения менее точным типом, вы обнаружите, что они равны равны в данном конкретном случае :
double d = 1.3d;
float f = 1.3f;
System.out.println((float) d == f); // Prints true
Однако это не гарантируется. Иногда приближение от десятичного литерала к двойному представлению, а затем приближение этого значения к представлению с плавающей запятой оказывается менее точным, чем приближение с прямой десятичной запятой к плавающему. Один пример этого 1.0000001788139343 (спасибо Stephentyrone за поиск этого примера).
Чуть безопаснее, вы можете сделать сравнение между двойными числами, но используйте литерал float
в исходном назначении:
double d = 1.3f;
float f = 1.3f;
System.out.println(d == f); // Prints true
В последнем случае это немного похоже на высказывание:
decimal10 oneThird = 0.3333300000
Однако , как указано в комментариях, вы почти наверняка не должны сравнивать значения с плавающей запятой с ==. Это почти никогда не то, что нужно делать, именно из-за такого рода вещей. Обычно, если вы хотите сравнить два значения, вы делаете это с неким «нечетким» сравнением на равенство, проверяя, достаточно ли эти два числа «достаточно близки» для ваших целей. Для получения дополнительной информации см. Страницу Java Traps: double .
Если вам действительно нужно проверить на абсолютное равенство, это обычно означает, что вы должны использовать другой числовой формат в первую очередь - например, для финансовых данных вы, вероятно, должны использовать BigDecimal
.