Ответ 1
TL; DR: NaN
имеют произвольное представление между 2 ^ 1024
и 2 ^ 1025
(ограничения не включены), а - 1.5 * 2 ^ 1024
(что возможно) NaN
происходит с быть тем, кого вы ударили.
Почему любые аргументы отключены
Что здесь происходит?
Вы входите в область поведения undefined. Или, по крайней мере, это то, что вы бы назвали на некоторых других языках. Отчет определяет round
следующим образом:
6.4.6 Принуждения и извлечение компонентов
Функции
ceiling
,floor
,truncate
иround
каждый принимают действительный дробный аргумент и возвращают интегральный результат....round x
возвращает ближайшее целое число вx
, четное целое, еслиx
равноудаленно между двумя целыми числами.
В нашем случае x
не представляет числа для начала. Согласно 6.4.6, y = round x
должно удовлетворять тому, что любой другой z
из round
codomain имеет равное или большее расстояние:
y = round x ⇒ ∀z : dist(z,x) >= dist(y,x)
Однако расстояние (ака вычитание) чисел определяется только для, ну, чисел. Если мы использовали
dist n d = fromIntegral n - d
мы скоро столкнемся: любая операция, включающая NaN
, снова вернет NaN
, а сравнения на NaN
завершатся неудачей, поэтому наше свойство выше не выполняется для каких-либо z
если x
был NaN
для начала. Если мы проверим NaN
, мы можем вернуть любое значение, но тогда наше свойство выполняется для всех пар:
dist n d = if isNaN d then constant else fromIntegral n - d
Итак, мы совершенно произвольны в том, что round x
вернется, если x
не было числом.
Почему мы получаем это большое количество независимо?
"ОК", я слышу, что вы говорите: "Это все прекрасно и денди, но почему я получаю этот номер?" Это хороший вопрос.
Предполагается ли это поведение?
Несколько. Это на самом деле не предназначено, но можно ожидать. Прежде всего, мы должны знать, как работает Double
.
Номера с плавающей точкой двойной точности IEE 754
A Double
в Haskell обычно представляет собой число с плавающей запятой двойной точности, совместимое с IEEE 754, то есть число, которое имеет 64 бита и представлено с помощью
x = s * m * (b ^ e)
где s
- один бит, m
- мантисса (52 бит), а e
- показатель степени (11 бит, floatRange
). b
является базой, а обычно 2
(вы можете проверить с помощью floadRadix
). Поскольку значение m
нормировано, каждое хорошо сформированное Double
имеет единственное представление.
IEEE 754 NaN
За исключением NaN
. NaN
представляется как e max +1, , а также ненулевая мантисса. Итак, если битполе
SEEEEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
представляет a Double
, какой действительный способ представить NaN
?
?111111111111000000000000000000000000000000000000000000000000000
^
То есть, для одного m
установлено значение 1
, а другое не требуется для установки этого понятия. Знак произвольный. Почему только один бит? Потому что его достаточно.
Интерпретировать NaN как Double
Теперь, когда мы игнорируем тот факт, что это некорректный Double
-a NaN
- и действительно, действительно, действительно хочет интерпретировать его как число, какое число мы получим?
m = 1.5
e = 1024
x = 1.5 * 2 ^ 1024
= 3 * 2 ^ 1024 / 2
= 3 * 2 ^ 1023
И вот, вот именно номер, который вы получаете за round (0/0)
:
ghci> round $ 0 / 0
-269653970229347386159395778618353710042696546841345985910145121736599013708251444699062715983611304031680170819807090036488184653221624933739271145959211186566651840137298227914453329401869141179179624428127508653257226023513694322210869665811240855745025766026879447359920868907719574457253034494436336205824
ghci> negate $ 3 * 2 ^ 1023
-269653970229347386159395778618353710042696546841345985910145121736599013708251444699062715983611304031680170819807090036488184653221624933739271145959211186566651840137298227914453329401869141179179624428127508653257226023513694322210869665811240855745025766026879447359920868907719574457253034494436336205824
Что приносит наше маленькое приключение к остановке. Мы имеем a NaN
, что дает a 2 ^ 1024
, и мы имеем некоторую ненулевую мантиссу, которая дает результат с абсолютным значением между 2 ^ 1024 < x < 2 ^ 1025
.
Обратите внимание, что это не единственный способ отображения NaN
:
В IEEE 754 NaN часто представлены в виде чисел с плавающей запятой с показателем e max + 1 и ненулевыми значениями. Реализации могут вставлять системную информацию в значение. Таким образом, не существует уникального NaN, а целого семейства NaN.
Для получения дополнительной информации см. классическую статью по номерам с плавающей запятой по Goldberg.