Чи дозволяється двигунам JS змінювати біти NaN?


12

У JavaScript значення NaN може бути представлено широким діапазоном 64-бітних подвійних значень внутрішньо. Зокрема, будь-який дубль із наступним розрядним поданням:

x111 1111 1111 xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx

Трактується як NaN. Моє запитання: припустимо, я за допомогою ArrayBuffers видав два 32-бітні унітки на номер JS, передаю його навколо, а потім повертаю до двох 32-бітних уінт. Чи відновлені біти будуть такими ж, як оригінал, або JS-двигунам дозволяється змінювати біти NaN за бажанням? Іншими словами, чи можна використовувати JS-номери для зберігання 64-бітових втрат?


2
Цікава ідея
Еверт

1
Тест я зробив. Схоже, щонайменше Node.js змінює біти за бажанням, спричиняючи втрату інформації.
MaiaVictor

1
У бік: Не кожен такий бітовий зразок являє собою NaN. Якщо всі x buts після першого дорівнюють нулю, це представляє нескінченність.
Eric Postpischil

Відповіді:


6

У розділі 6.1.6 «Тип номера» у 9- му виданні ECMA-262 (стандарт, якому призначений JavaScript) йдеться:

… Окремі значення IEEE стандарту IEEE 9007199254740990 (тобто 2 53 -2) представлені в ECMAScript як єдине спеціальне значення NaN… У деяких реалізаціях зовнішній код може виявити різницю між різними значеннями Not-a-Number, але така поведінка залежить від реалізації; до коду ECMAScript, всі значення NaN не відрізняються один від одного.

24.1.17 "NumberToRawBytes (тип, значення, isLittleEndian)" говорить:

… Якщо значення NaN, rawBytes може бути встановлений для будь-якої обраної програми кодування IEEE 754-2008 binary64 формату кодування без числа. Реалізація завжди повинна вибирати одне і те ж кодування для кожної реалізації, що відрізняє значення NaN.

Я не бачу інших уривків, які згадують про NaN, які висвітлюються з цього питання. З одного боку, 24.1.17 ефективно говорить нам, що біти NaN повинні бути збережені при перетворенні NaN в необроблені байти. Однак більше нічого, схоже, не говорить про те, що біти повинні зберігатися в інших операціях. Можна зробити висновок, що це є наміром, оскільки ця вимога в 24.1.17 не буде служити ніякій меті, якщо біти можуть бути довільно змінені будь-якою іншою операцією. Але я б не покладався на реалізацію JavaScript, щоб реалізувати це відповідно до цього наміру.


1

Одного разу я задав питання Java, про апаратну залежність значень NaN, і було помічено, що деякі процесори мовчки перетворять "сигнальний NaN" в "тихий NaN" (встановлюючи тихий біт NaN), коли завантажується значення NaN в регістр процесора. Отже, принаймні один із бітів, тихий біт NaN, ви не можете використовувати для зберігання довільних даних.

Використання інших бітів, якщо встановлено тихий біт NaN, ймовірно, безпечно. Але все ж, здається, тут є місце для залежності від впровадження, а отже, і до гарантій.

Така проблема полягає в тому, що звичайні операції з мовою уникають робити все, що залежить від внутрішнього значення NaN, і вважають за краще ставитись до всіх NaN як до "просто NaN".


0

Оригінальний стандарт IEEE-754 навмисно залишив біти NaN аж до реалізації. Це дало підказки, такі як

Ви можете поставити оригінальну адресу пам'яті, де створено NaN.

Тим часом арифметика має конкретні правила щодо того, що робити з NaN, і це не має нічого спільного з бітами внизу. Я не думаю, що це навіть говорить про те, що робити при додаванні двох NaN - тримати біти від одного з них порівняно з іншим набором біт. Тільки що результат все-таки повинен бути NaN.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.