tl; dr это связано с очень глубокими подробностями того, как NaN
s представлены в двоичном виде. Вы можете обойти это, используя digest(.,ascii=TRUE)
...
В продолжение ответа @ Jozef: обратите внимание на полужирные цифры ...
> base::serialize(Inf-Inf,connection=NULL)
[1] 58 0a 00 00 00 03 00 03 06 00 00 03 05 00 00 00 00 05 55 54 46 2d 38 00 00
[26] 00 0e 00 00 00 01 <strong>ff</strong> f8 00 00 00 00 00 00
> base::serialize(NaN,connection=NULL)
[1] 58 0a 00 00 00 03 00 03 06 00 00 03 05 00 00 00 00 05 55 54 46 2d 38 00 00
[26] 00 0e 00 00 00 01 <strong>7f</strong> f8 00 00 00 00 00 00
В качестве альтернативы, используя pryr::bytes()
...
> bytes(NaN)
[1] "7F F8 00 00 00 00 00 00"
> bytes(Inf-Inf)
[1] "FF F8 00 00 00 00 00 00"
Статья Википедии о формате с плавающей запятой / NaNs гласит:
Некоторые операции с арифметикой с плавающей точкой недопустимы, например, получение квадратного корня из отрицательного числа. Достижение недопустимого результата называется исключением с плавающей точкой. Исключительный результат представлен специальным кодом, называемым NaN, для «Не числа». Все NaN в IEEE 754-1985 имеют этот формат:
- знак = 0 или 1.
- смещенная экспонента = все 1 бит.
- дробь = все, кроме всех 0 бит (поскольку все 0 бит представляют бесконечность).
Знак - первый бит; показатель степени - следующие 11 битов; дробь это последние 52 бита. При переводе первых четырех шестнадцатеричных цифр, приведенных выше, в двоичную форму, Inf-Inf
равно 1111 1111 1111 0100
(знак = 1; экспонента - все единицы, как требуется; дробь начинается с 0100
), тогда как NaN
равно 0111 1111 1111 0100
(то же самое, но со знаком = 0).
Чтобы понять , почему Inf-Inf
заканчивается знаковым битом 1, а NaN
имеет знаковый бит 0, вам, вероятно, придется глубже изучить способ реализации арифметики с плавающей запятой на этой платформе. ..
Возможно, стоит поднять проблему в дайджесте репозитория GitHub по этому поводу; Я не могу придумать элегантный способ сделать это, но кажется разумным, что объекты, где identical(x,y)
равен TRUE
в R, должны иметь идентичные хэши ... Обратите внимание, что identical()
специально игнорирует эти различия в битовых комбинациях с помощью аргумента single.NA
(по умолчанию TRUE
):
single.NA: логическое указание, если концептуально существует только один числовой
‘NA’ и один ‘NaN’; «Single.NA = FALSE» различает бит
узоры.
В коде C похоже, что R просто использует оператор C !=
для сравнения NaN
значений , если не включено побитовое сравнение, и в этом случае он явно проверяет равенство памяти места: см. здесь . То есть оператор сравнения C, по-видимому, обрабатывает различные типы значений NaN
как эквивалентные ...