Проверьте два значения float/double для точного равенства
Что такое элегантный, читаемый и невербальный способ сравнения двух значений с плавающей запятой для точного равенства?
Проще, как это может показаться, его злая проблема. Оператор ==
не выполняет работу над NaN и также имеет специальное лечение для нуля:
(+0.0 == -0.0) -> true
Double.NaN == Double.NaN -> false
Но я хочу определить, являются ли два значения одинаковыми (но мне не нужны разные шаблоны NaN, поэтому любой NaN == любой другой NaN → true).
Я могу сделать это с этой уродливой частью кода монстра:
Double.doubleToLongBits(a) == Double.doubleToLongBits(b)
Есть ли лучший способ написать это (и сделать очевидным намерение)?
Ответы
Ответ 1
То, что у вас есть, - это лучший способ сделать это, я бы сказал. Это дает понять, что вас интересует поразрядное представление значения. Вы преобразовываете эти биты в long
как удобный 64-битный тип, который не имеет каких-либо фанковых действий.
Если вы не хотите, чтобы он часто появлялся в вашей кодовой базе, просто добавьте метод для его переноса:
public static boolean bitwiseEqualsWithCanonicalNaN(double x, double y) {
return Double.doubleToLongBits(x) == Double.doubleToLongBits(y);
}
Обратите внимание, что в соответствии с вашим вопросом это не отличает разные значения NaN. Если вы хотите сделать это позже, вам нужно будет использовать Double.toRawLongBits
.
Ответ 2
Вы можете использовать
Double.compare(a, b) == 0
Из javadoc для compareTo
- Double.NaN считается этим методом равным себе и больше всех других двойных значений (включая Double.POSITIVE_INFINITY).
- 0.0d считается этим методом больше -0.0d.