Как стать автором
Обновить

Комментарии 26

Насколько я понимаю, то что Nan!=Nan - требование IEEE 754. Но почему так сделали? ИМХО NaN это обычный none в опциональном типе, а создатели стандарта чисел с плавающей точкой все зачем-то усложнили.

NaN и отсутствие числа - разные вещи

НЛО прилетело и опубликовало эту надпись здесь

Maybe Float всем лучше! Обнаружил тут крейт Noisy Float, не такой уж непопулярный, который как раз-таки с безопасным float

UPD: безопасный он довольно условно: просто паникует при любом ненормальном числе. Видимо, это поведение более востребовано, чем аккуратный Option вокруг почти всего

Возможно, потому же, что в SQL NULL <> NULL

NaN получается в результате разных операций. Например вы что-то поделили на 0 и получили NaN и вы взяли квадратный корень из -1 и получили NaN. Язык не может гарантировать равенство результатов, которые он не может выразить числом.

НЛО прилетело и опубликовало эту надпись здесь

Я думаю имелось ввиду, что /0=∞, а -1^1/2 — мнимое число. Т.е результаты разные, но представлены одним и тем же NaN, который эдакий "всё плохо". И чтобы не сравнивали разные виды "всё плохо" с друг другом...

НЛО прилетело и опубликовало эту надпись здесь

Выражусь более понятно. Вы же согласны, что следующее сравнение не является истинным с точки зрения математики:

if (1/0 == Math.sqrt(-1)) {
   console.log('1/0 equal to sqrt(-1)');
}

А теперь замените левую и правую часть сравнения на NaN. Почему в этом результат должен отличаться.

НЛО прилетело и опубликовало эту надпись здесь

Потому что JS не умеет комплексные числа, и так как они не могут быть выражены через тип number, то мы имеем NaN. И поскольку JS не может корректно представить левую и правую часть типом number он заменяет их на NaN.

Если в перспективе number расширят на комплексные числа или введут новый тип, то и sqrt(-1) перестанет быть NaN, но пока так.

НЛО прилетело и опубликовало эту надпись здесь

Перечитайте limits/пределы из математики (стремящиеся к бесконечности, например) и тогда поймёте почему разные Nan разные (в общем случае).

НЛО прилетело и опубликовало эту надпись здесь

>> не являются числами

Совершенно верно! Nan - Not a number ))

https://uk.wikipedia.org/wiki/NaN - там все написано, если не верите мне

Был бы явный Option, было бы логично: (Some(5) == Some(5)) == Some(true), при этом (Some(5) == None) == None) и (None == None) = None).

Но Option тут половинчатый, и такое решение выглядит довольно логично. В конце концов, NaN представляет разные ситуации не-чисел, например, parseInt("blah") и "".charCodeAt(1). Было бы странно говорить, что они равны в контексте сравнения чисел.

НЛО прилетело и опубликовало эту надпись здесь

Хороший вопрос! Для меня сравнение тут возможно трёх видов (Number во всех трёх случаях включает не NaN, Option<Number> — включает):

  1. Option<Number> -> Option<Number> -> Option<Bool>, когда сравниваются только числа, а не-числа приводят к принципиально другому результату. Это как в SQL с nullable-типами: NULL = NULL даёт NULL

  2. Option<Number> -> Option<Number> -> Bool по типу SQL-ного IS NOT DISTINCT FROM (оно же <=> в MySQL). Это Ваш вариант

  3. Option<Number> -> Option<Number> -> Bool , в виде модификации первого варианта, когда Some(true) приравнивается к true, а всё остальное — к false. Это вариант из IEEE 754. Кстати, преобразование Some<Bool> в Bool здесь по аналогии с работой WHERE в SQL: отбираются только строки со значением условия TRUE, а FALSE и NULL — нет, происходит эдакое впихивание трёх значенийOption<Bool> в два значения Bool.

Я думаю о том, что блок с условием NaN == NaN не выполнится, по аналогии с тем, как в SQL не отберутся строки с NULL = NULL.

Кстати, читал тут документацию, и почему-то NaN ** 0 в Javascript даёт единицу. Вероятно, потому что нулевая степень чего угодно, даже жаренной с грибами картошки, даёт всё равно единицу.

НЛО прилетело и опубликовало эту надпись здесь

~==~ выглядит ровно как сравнение в SQL с учётом nullable, на этот счёт недавно была полемическая статья.

Я совершенно согласен, что в целом для Maybe обыкновенный == выглядит удобнее почти во всех случаях.

Кстати, в IEEE 754 прочитал (раздел 5.11):

Four mutually exclusive relations are possible: less than, equal, greater than, and unordered. The last case arises when at least one operand is NaN. Every NaN shall compare unordered with everything, including itself.

Соответственно, для каждой операции сравнения разный набор этих вариантов превращается в true или false, там ниже таблицы истинности.

Как это работает — понятно, а что это с точки зрения типов и как это думать — перестал понимать совсем.

Решение проблемы — запрет на прямое сравнение с NaN
Теперь разработчики видят ошибку

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

речь идёт про TypeScript, тоесть отлавливаться данная проверка будет на этапе транспиляции

1/0 === 2/0, потому что оба равны +Infinity

Это, во многом, нацелено именно на сравнение с константой NaN. Потому что на автомате часто пишут x != NaN для проверки на NaN, но эта проверка по правилам IEEE754 всегда истинна. Теперь случаи такой проверки будут подсвечены как ошибки.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий