Comments 29
Глядя на это все иногда возникает чувство, что тут немного перемудрили…
Вообще-то 0**0 неопределено и может быть честным NaN
https://en.wikipedia.org/wiki/Zero_to_the_power_of_zero#Treatment_on_computers
Это зависит от задачи. Скажем, при определении кривой Безье соглашение о том, что 0**0=1 упрощает формулу.
Где-то тут на Хабре была статья о том, что в некоторых языках программирования определено три разных функции возведения в степень, отличающиеся только поведением в точке 0**0.
log(-1) = NaN
, это число ещё и необязательно вещественное (в данном случае комплексное).Еще один прикол NaN — он не равен ничему, даже самому себе
>>> nan != nan
True
NaN != NaN
. Только isnan()
вернёт правильный результат.Это было введено в стандарт для того, чтобы не пришлось добавлять в языки операцию проверки на NaN.
В ранних языках стандартным способом проверки x на NaN было условие x != x.
Я нашел ответ на SO от бывшего члена комитета IEEE754.
More importantly, there was no isnan( ) predicate at the time that NaN was formalized in the 8087 arithmetic; it was necessary to provide programmers with a convenient and efficient means of detecting NaN values that didn’t depend on programming languages providing something like isnan( ) which could take many years.
https://stackoverflow.com/questions/1565164/what-is-the-rationale-for-all-comparisons-returning-false-for-ieee754-nan-values/1573715#1573715
Если функция возводится в степень и при этом стремится к 0, то в результате получится 1, вне зависимости от того, какое значение имеет функция.
Кто-то не знаком с определением числа e, например. lim_{x -> inf} (1 + 1/x) ^ (1/x) = e != 1.
Я подумал и угадал верный результат. При этом я даже едва знаком с питоном. По-моему, всё предельно логично.
Я подумал и угадал верный результат.
С учетом всех ваших статей на Хабре — вам можно верить на слово.
По-моему, всё предельно логично.
Верно. Возможно раньше я бы тоже ответил правильно, но уже пол года активно использую Pandas, а там NaN начинает восприниматься буквально, как пропущенные (или отсутствующие) данные. Перестаешь воспринимать NaN как число.
Интересно, а это поведение тоже выглядит предельно логично?
>>> 0*nan
nan
Я угадал верный результат только потому что раз есть вопрос (и целая статья на эту тему), значит не очень очевидное поведение. Логическо только 2 подошла. Но, стоит признаться, я думал что приоритет у вычислительного рака NaN выше и все функции, которые на него натыкаются, так же должны возвращать NaN без исключений.
Более того, в некоторых языках (не будем тыкать в js пальцем) за NaN может скрываться не какое-то число, которое не влезло в дабл или что-то в этом духе, а строка или вообще объект. В нем выражение Math.pow(1, "give me a power!")
или даже с смайликом в качестве степени — возможно. Единица в степени эмоджи, равная единице, выглядит странно.
Справедливости ради, в JS все наоборот, как обычно:
1 ** NaN // NaN
"Give me a power" ** 0 // 1
new Object() ** 0 // 1
Я как-то писал очень похожую статью:
https://m.habr.com/ru/post/454352/
Имеет ли смысл использовать такое на практике? Думаю, что лучше не стоит.
Правильно думаете. NaN — это семейство значений с плавающей точкой, у которых экспонента состоит полностью из 1, а мантисса не состоит полностью из нулей. Поэтому nan
как литерал не обязан быть по хэшу равен nan
, полученному в ходе вычислений.
По теме статьи — вопрос дискуссионный, что считать наиболее правильным подходом. Как по мне, надо бы различать два случая:
1.0**nan
должно бытьnan
, т.к. 1.0 обозначает лишь некоторое число между 1-eps/2 и 1+eps. В частности,(1 + 10**(-10))**nan
—nan
, но(float32(1 + 10**(-10)))**nan == 1
выглядит несколько абсурдно1**nan
(1 — целое число) вполне можно взять равным 1.0, т.к. целочисленный литерал тут обозначает точную единицу без какой-либо погрешности
NaN все еще может немного удивить