I motori JS possono cambiare i bit di una NaN?


12

In JavaScript, il valore NaN può essere rappresentato internamente da una vasta gamma di doppi a 64 bit. In particolare, qualsiasi doppio con la seguente rappresentazione bit a bit:

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

Viene interpretato come NaN. La mia domanda è: supponiamo di aver lanciato due uint a 32 bit su un numero JS usando ArrayBuffers, di passarlo in giro, quindi di ricondurlo a due uint a 32 bit. I bit recuperati saranno gli stessi dell'originale o i motori JS possono cambiare i bit di una NaN a piacimento? In altre parole, i numeri JS possono essere utilizzati per memorizzare in modalità perdita a 64 bit?


2
Idea interessante
Evert

1
Un test che ho fatto. Sembra che almeno Node.js cambi i bit a piacimento, causando la perdita di informazioni.
MaiaVictor

1
A parte: non tutti questi pattern di bit rappresentano un NaN. Se tutti i x ma dopo il primo sono zero, rappresenta un infinito.
Eric Postpischil,

Risposte:


6

ECMA-262 9 th Edition, giugno 2018, (lo standard a cui JavaScript è destinato a conformarsi) dice, in 6.1.6 "Il tipo di numero":

... il 9007199254740990 (ovvero 2 53 -2) distinti "Not-a-Number" dello standard IEEE sono rappresentati in ECMAScript come un singolo valore NaN speciale ... In alcune implementazioni, il codice esterno potrebbe essere in grado di rilevare una differenza tra vari valori non numerici, ma tale comportamento dipende dall'implementazione; al codice ECMAScript, tutti i valori NaN sono indistinguibili l'uno dall'altro.

24.1.17 "NumberToRawBytes (tipo, valore, isLittleEndian)" dice:

… Se il valore è NaN, rawBytes può essere impostato su qualsiasi implementazione scelta Codifica Not-a-Number del formato binario64 IEEE 754-2008. Un'implementazione deve sempre scegliere la stessa codifica per ciascun valore NaN distinguibile dell'implementazione ...

Non vedo altri passaggi che menzionano NaN che sono illuminanti su questa domanda. Da un lato, 24.1.17 ci dice effettivamente che i bit di un NaN devono essere preservati quando si converte il NaN in byte grezzi. Tuttavia, nient'altro sembra dirci che i bit devono essere conservati in altre operazioni. Si potrebbe dedurre che questo è l'intento, perché questo requisito in 24.1.17 non servirebbe a nulla se i bit potessero essere arbitrariamente modificati da qualsiasi altra operazione. Ma non farei affidamento sulle implementazioni JavaScript per averlo implementato in conformità con quell'intento.


1

Una volta ho posto una domanda a Java, sulla dipendenza hardware dei valori NaN, ed è stato notato che alcune CPU convertiranno silenziosamente un "NaN di segnalazione" in un "NaN silenzioso" (impostando il bit NaN silenzioso) quando viene caricato un valore NaN in un registro del processore. Quindi almeno uno dei bit, il bit NaN silenzioso, non è possibile utilizzare per la memorizzazione di dati arbitrari.

L'uso degli altri bit, purché sia ​​impostato il bit NaN silenzioso, è probabilmente sicuro. Ma sembra che ci sia ancora spazio per la dipendenza dall'implementazione, e quindi nessuna garanzia.

Questo tipo di problema è il motivo per cui le normali operazioni linguistiche evitano di fare qualsiasi cosa dipenda dal valore interno di una NaN e preferiscono trattare tutte le NaN come "solo NaN".


0

Lo standard IEEE-754 originale ha deliberatamente lasciato i bit di un NaN fino all'implementazione. Ha fornito suggerimenti, come

È possibile inserire l'indirizzo di memoria originale di dove è stato creato il NaN.

Nel frattempo, l'aritmetica ha regole specifiche su cosa fare con un NaN, e questo non ha nulla a che fare con i bit in fondo. Non credo che dica nemmeno cosa fare quando si aggiungono due NaN: mantenere i bit di uno di essi anziché creare un altro set di bit. Solo che il risultato deve essere ancora un NaN.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.