Czy silniki JS mogą zmieniać bity NaN?

12

W JavaScript wartość NaN może być reprezentowana wewnętrznie przez szeroki zakres 64-bitowych dubletów. W szczególności każde podwójne z następującą reprezentacją bitową:

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

Jest interpretowany jako NaN. Moje pytanie brzmi: załóżmy, że rzutuję dwa 32-bitowe odcienie na numer JS za pomocą ArrayBuffers, przekazuję je, a następnie rzutuję z powrotem na dwa 32-bitowe zmiany. Czy odzyskane bity będą takie same jak oryginalne, czy też silniki JS mogą dowolnie zmieniać bity NaN? Innymi słowy, czy numery JS mogą być używane do przechowywania stratnych 64-bitów?

MaiaVictor
źródło
2
Ciekawy pomysł
Evert
1
Test zrobiłem. Wydaje się, że przynajmniej Node.js zmienia bity do woli, powodując utratę informacji.
MaiaVictor,
1
Poza tym: Nie każdy taki wzór bitowy reprezentuje NaN. Jeśli wszystkie x oprócz pierwszego są równe zero, oznacza to nieskończoność.
Eric Postpischil

Odpowiedzi:

6

ECMA-262 9 th Edition, czerwiec 2018 (standard, do którego JavaScript ma na celu zgodne) mówi w 6.1.6 „numer typu”:

… 9007199254740990 (czyli 2 53 -2) odrębne wartości „nie-liczba” standardu IEEE są reprezentowane w ECMAScript jako pojedyncza specjalna wartość NaN.… W niektórych implementacjach kod zewnętrzny może wykryć różnicę między różnymi wartościami „nie-liczba”, ale takie zachowanie zależy od implementacji; do kodu ECMAScript wszystkie wartości NaN są nierozróżnialne.

24.1.17 „NumberToRawBytes (typ, wartość, isLittleEndian)” mówi:

… Jeśli wartością jest NaN, rawBytes może być ustawione na dowolną implementację wybranego kodowania binarnego w formacie IEEE 754-2008 Not-a-Number. Implementacja musi zawsze wybierać to samo kodowanie dla każdej implementowalnej wartości NaN…

Nie widzę żadnych innych fragmentów, które wspominałyby NaN, które byłyby pouczające w tej kwestii. Z jednej strony, 24.1.17 skutecznie mówi nam, że bity NaN muszą zostać zachowane podczas konwersji NaN na surowe bajty. Jednak nic więcej nie wydaje się mówić, że bity należy zachować w innych operacjach. Można wywnioskować, że taka jest intencja, ponieważ wymaganie zawarte w 24.1.17 nie miałoby sensu, gdyby bity mogły być dowolnie zmienione przez jakąkolwiek inną operację. Ale nie polegałbym na implementacjach JavaScript, aby zaimplementować to zgodnie z tą intencją.

Eric Postpischil
źródło
1

Kiedyś zadałem pytanie dla Javy, dotyczące zależności sprzętowej wartości NaN, i zauważyłem, że niektóre procesory po cichu przekonwertują „sygnał NaN” na „cichy NaN” (ustawiając cichy bit NaN), gdy załadowana zostanie wartość NaN do rejestru procesora.Co najmniej jeden z bitów, cichy bit NaN, nie można użyć do przechowywania dowolnych danych.

Prawdopodobnie używa się innych bitów, o ile ustawiony jest cichy bit NaN bezpieczne. Ale nadal wydaje się, że jest tu miejsce na zależność od implementacji, a zatem nie ma gwarancji.

Tego rodzaju problem polega na tym, że w normalnych operacjach językowych unika się robienia czegokolwiek, co zależy od wewnętrznej wartości NaN, i woli traktować wszystkie NaN jako „tylko NaN”.

Boann
źródło
0

Oryginalny standard IEEE-754 celowo pozostawił bity NaN do wdrożenia. Dostarczył wskazówek, takich jak

Możesz podać oryginalny adres pamięci, w którym utworzono NaN.

Tymczasem arytmetyka ma określone reguły dotyczące tego, co zrobić z NaN, a to nie ma nic wspólnego z bitami na dole. Nie sądzę, żeby mówiło nawet, co zrobić, dodając dwa NaN - zachowaj bity z jednego z nich, a nie stwórz inny zestaw bitów. Tyle, że wynikiem musi być wciąż NaN.

Rick James
źródło