Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are JS engines allowed to change the bits of a NaN?

In JavaScript, the NaN value can be represented by a wide range of 64-bit doubles internally. Specifically, any double with the following bitwise representation:

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

Is interpreted as a NaN. My question is: suppose I cast two 32-bit uints to a JS Number using ArrayBuffers, pass it around, then cast it back to two 32-bit uints. Will the recovered bits be the same as the original, or are JS engines allowed to change the bits of a NaN at will? In other words, can JS numbers be used to store 64-bits losslesly?

like image 424
MaiaVictor Avatar asked Nov 07 '19 20:11

MaiaVictor


People also ask

How do you fix NaN?

Nan means “Not a number”, this is because inside your cube function, you're not calling the square function, but getting it's contents. Change return x * square; with return x * square(x); and it should work.

Is NaN false in JavaScript?

There are only six falsey values in JavaScript: undefined , null , NaN , 0 , "" (empty string), and false of course.

Why is NaN == NaN false?

Although either side of NaN===NaN contains the same value and their type is Number but they are not same. According to ECMA-262, either side of == or === contains NaN then it will result false value.

Is NaN a data type in JavaScript?

In JavaScript, NaN is short for "Not-a-Number". In JavaScript, NaN is a number that is not a legal number. The Number. isNaN() method returns true if the value is NaN , and the type is a Number.


2 Answers

ECMA-262 9th Edition, June 2018, (the standard to which JavaScript is intended to conform) says, in 6.1.6 “The Number Type”:

… the 9007199254740990 (that is, 253-2) distinct “Not-a-Number” values of the IEEE Standard are represented in ECMAScript as a single special NaN value.… In some implementations, external code might be able to detect a difference between various Not-a-Number values, but such behaviour is implementation-dependent; to ECMAScript code, all NaN values are indistinguishable from each other.

24.1.17 “NumberToRawBytes ( type, value, isLittleEndian )” says:

… If value is NaN, rawBytes may be set to any implementation chosen IEEE 754-2008 binary64 format Not-a-Number encoding. An implementation must always choose the same encoding for each implementation distinguishable NaN value.…

I do not see any other passages that mention NaN that are illuminating on this question. On one hand, 24.1.17 effectively tells us the bits of a NaN must be preserved when converting the NaN to raw bytes. However, nothing else appears to tell us the bits must be preserved in other operations. One might deduce that this is the intent, because this requirement in 24.1.17 would serve no purpose if the bits could be arbitrarily changed by any other operation. But I would not rely on JavaScript implementations to have implemented this in conformance with that intent.

like image 188
Eric Postpischil Avatar answered Oct 29 '22 22:10

Eric Postpischil


I once asked a question for Java, about hardware-dependence of NaN values, and it was noticed that some CPUs will silently convert a "signaling NaN" into a "quiet NaN" (setting the quiet NaN bit) when a NaN value is loaded into a processor register. So at least one of the bits, the quiet NaN bit, you cannot use for storing arbitrary data.

Using the other bits, so long as the quiet NaN bit is set, is probably safe. But still there seems to be room for implementation-dependence here, and hence no guarantee.

This sort of problem is why normal language operations avoid doing anything that depends on the internal value of a NaN, and prefer to treat all NaNs as "just NaN".

like image 40
Boann Avatar answered Oct 29 '22 21:10

Boann