В JavaScript, почему ноль, деленный на ноль, возвращает NaN, а любой другой, деленный на ноль, возвращает бесконечность?

Мне кажется, что код

console.log(1 / 0)

должен возвращать NaN, но вместо этого возвращает Infinity. Однако этот код:

console.log(0 / 0)

возвращает NaN. Может ли кто-нибудь помочь мне понять причину этой функции? Это не только кажется непоследовательным, но и неправильным в случае x / 0, где x !== 0


person Bloodyaugust    schedule 16.09.2013    source источник
comment
stackoverflow.com/questions/3215120/   -  person PSL    schedule 17.09.2013
comment
Здесь есть достойное руководство   -  person    schedule 17.09.2013
comment
В любом числе бесконечное количество нулей, поэтому x / 0 === Infinity мне кажется логичным.   -  person Ken Herbert    schedule 17.09.2013


Ответы (3)


Потому что именно так определяется плавающая точка (в более общем смысле, чем просто Javascript). См. Например:

Грубо говоря, вы можете представить 1/0 как предел 1 / x, когда x стремится к нулю (справа). А 0/0 вообще не имеет разумной интерпретации, следовательно, NaN.

person Oliver Charlesworth    schedule 16.09.2013

Помимо ответов, основанных на математической концепции нуля, особое внимание уделяется числам с плавающей запятой. Каждый результат потери значимости, каждое ненулевое число, абсолютная величина которого слишком мала, чтобы представить его как ненулевое число, представляется как ноль.

0/0 действительно может быть 1e-500 / 1e-600, или 1e-600 / 1e-500, или многими другими отношениями с очень маленькими значениями.

Фактическое соотношение может быть любым, поэтому нет значимого числового ответа, и результатом должно быть NaN.

Теперь рассмотрим 1/0. Не имеет значения, представляет ли 0 1e-500 или 1e-600. В любом случае, при делении произойдет переполнение, и правильным результатом будет значение Infinity, используемое для представления переполнения.

person Patricia Shanahan    schedule 17.09.2013
comment
Здесь важен язык. Маленькие числа не отображаются как ноль, а ноль не представляет собой маленькие числа. Эта формулировка заставляет людей неправильно думать о приближении с плавающей запятой. Деление с плавающей запятой может возвращать ноль для операций, математический результат которых крошечный, но это потому, что деление с плавающей запятой определено для возврата представимого значения, ближайшего к точному значению, а не потому, что оно определено для приблизительного представления частного. Каждое значение с плавающей запятой представляет собой ровно одно число, а не интервал. - person Eric Postpischil; 17.09.2013
comment
@EricPostpischil Да и нет. Да, арифметика с плавающей запятой IEEE 754 четко определена, с определенным результатом для каждого вычисления и одним значением для каждого конечного числа. Нет, потому что эта система в отдельности была бы бесполезной. Его практическая полезность заключается в том, что во многих случаях он дает хорошие приближения к результатам научных или инженерных расчетов, которые фактически определяются в терминах арифметики действительных чисел. Я подумаю, как переформулировать свой ответ, чтобы правильно различать арифметику с действительными числами и арифметику с плавающей запятой. - person Patricia Shanahan; 17.09.2013
comment
@PatriciaShanahan: Мне нравится думать об этом так: значение с плавающей запятой представляет собой то, что будет рассматриваться как точное число в будущем, но во многих случаях будет представлять результат операции, точный числовой результат которой находится в пределах 1 / 2ulp поступательного значения. Если a, b и c находятся в пределах одного порядка величины друг от друга, и нужно отображать сумму с точностью до четырех значащих цифр, зная, что a+b+c будет значением в пределах 1 ppm от правильного [фактическая точность на самом деле лучше ] может оказаться более полезным, чем точное определение ошибки. - person supercat; 18.09.2013

Я понимаю, что это устарело, но я думаю, что важно отметить, что в JS также есть -0, который отличается от 0 или +0, что делает эту функцию JS гораздо более логичной, чем на первый взгляд.

1 / 0 -> Infinity
1 / -0 -> -Infinity 

что логически имеет смысл, поскольку в исчислении причина деления на 0 не определена исключительно потому, что левый предел уходит на отрицательную бесконечность, а правый предел - на положительную бесконечность. Поскольку -0 и 0 - это разные объекты в JS, имеет смысл применять положительный 0 для оценки положительного Infinity и отрицательный 0 для оценки отрицательного Infinity

Эта логика не применима к 0/0, что является неопределенным. В отличие от 1/0, мы можем получить два результата, взяв ограничения с помощью этого метода с 0/0

lim h->0(0/h) = 0
lim h->0(h/0) = Infinity

что, конечно, непоследовательно, поэтому в результате получается NaN

person Matthew Ciaramitaro    schedule 14.04.2017
comment
Интересно, но неполно. Подумайте lim h -> 0 (h / h). Поскольку в JS есть положительные и отрицательные нули, также должны быть положительный и отрицательный предел. Таким образом, только 0 / -0 и -0/0 должны давать NaN. Остальные должны быть положительной или отрицательной бесконечностью. Конечно, математик во мне все еще плачет, как ребенок. - person SMBiggs; 07.03.2019
comment
@SMBiggs, почему lim h -> 0 (h / h), а не lim h -> 0 (2h / h) (например)? Нет последовательного результата. - person trincot; 24.08.2020
comment
В разделе комментариев у меня не было места для включения бесконечных вариаций, дающих тот же результат. Вместо этого я использовал простейшую форму, которую только мог придумать, которая создает график рассматриваемой формы (и ограничений). - person SMBiggs; 25.08.2020