Pull to refresh

Comments 26

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

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

UFO just landed and posted this here

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

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

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

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

UFO just landed and posted this here

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

UFO just landed and posted this here

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

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

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

UFO just landed and posted this here

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

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

UFO just landed and posted this here

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

UFO just landed and posted this here

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

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

UFO just landed and posted this here

Хороший вопрос! Для меня сравнение тут возможно трёх видов (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 даёт единицу. Вероятно, потому что нулевая степень чего угодно, даже жаренной с грибами картошки, даёт всё равно единицу.

UFO just landed and posted this here

~==~ выглядит ровно как сравнение в 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 всегда истинна. Теперь случаи такой проверки будут подсвечены как ошибки.

Sign up to leave a comment.