Существует интересная разница между ==
и equals
для Float
и Double
типов: они трактуют NaN
по-разному:
scala> Double.NaN == Double.NaN
res3: Boolean = false
scala> Double.NaN equals Double.NaN
res4: Boolean = true
Редактировать: Как было отмечено в комментарии - «это также происходит в Java» - зависит от того, что именно это :
public static void main(final String... args) {
final double unboxedNaN = Double.NaN;
final Double boxedNaN = Double.valueOf(Double.NaN);
System.out.println(unboxedNaN == unboxedNaN);
System.out.println(boxedNaN == boxedNaN);
System.out.println(boxedNaN.equals(boxedNaN));
}
Это напечатает
false
true
true
Итак, unboxedNan
дает false
при сравнении на равенство, потому что именно так его определяют числа с плавающей запятой IEEE, и это действительно должно происходить в каждом языке программирования (хотя это как-то смешивается с понятием идентичности).
Штрихованный NaN дает true для сравнения, используя ==
в Java, когда мы сравниваем ссылки на объекты.
У меня нет объяснения для случая equals
, ИМХО, он действительно должен вести себя так же, как ==
для распакованных двойных значений, но это не так.
В переводе на Scala дело обстоит немного сложнее, поскольку Scala объединяет примитивные и объектные типы в Any
и переводит в примитивный двойник и коробочный двойник по мере необходимости. Таким образом, scala ==
, по-видимому, сводится к сравнению примитивных NaN
значений, но equals
использует значение, определенное для значений Double в штучной упаковке (происходит много неявного преобразования магии, и есть что-то, что превращается в double с помощью RichDouble
).
Если вам действительно нужно выяснить, действительно ли что-то NaN
, используйте isNaN
: