admin管理员组文章数量:1355278
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?
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?
Share Improve this question asked Nov 7, 2019 at 20:55 MaiaVictorMaiaVictor 53.1k47 gold badges158 silver badges302 bronze badges 3- 2 Interesting idea – Evert Commented Nov 7, 2019 at 20:57
- 1 A test I made. Seems like at least Node.js changes the bits at will, causing loss of information. – MaiaVictor Commented Nov 7, 2019 at 21:53
- 1 Aside: Not every such bit pattern represents a NaN. If all x buts after the first are zero, it represents an infinity. – Eric Postpischil Commented Nov 8, 2019 at 8:23
4 Answers
Reset to default 6ECMA-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.
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".
According to the IEEE-754 standard, for non-signaling NaNs trailing bits should be preserved, and if they represent something canonical, they shall be preserved.
For an operation with quiet NaN inputs, other than maximum and minimum operations, if a floating-point result is to be delivered the result shall be a quiet NaN which should be one of the input NaNs. If the trailing significand field of a decimal input NaN is canonical then the bit pattern of that field shall be preserved if that NaN is chosen as the result NaN.
I wouldn't count on it. And for the leading sign bit, you definitely can't count on it.
For all other operations, this standard does not specify the sign bit of a NaN result, even when there is only one input NaN, or when the NaN is produced from an invalid operation.
The original IEEE-754 standard deliberately left the bits of a NaN up to the implementation. It did provide hints, such as
You might put the original memory address of where the NaN was created.
Meanwhile, arithmetic has specific rules about what to do with a NaN, and that has nothing to do with the bits in the bottom. I don't think it even says what to do when adding two NaNs -- keep the bits from one of them versus make up another set of bits. Just that the result must still be a NaN.
本文标签: javascriptAre JS engines allowed to change the bits of a NaNStack Overflow
版权声明:本文标题:javascript - Are JS engines allowed to change the bits of a NaN? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1743952991a2567631.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论