Javascript JS引擎是否允许更改NaN的位?

Javascript JS引擎是否允许更改NaN的位?,javascript,ieee-754,Javascript,Ieee 754,在JavaScript中,NaN值可以在内部由一系列64位双精度表示。具体而言,任何具有以下按位表示的双精度: x111 1111 1111 xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx 被解释为NaN。我的问题是:假设我使用ArrayBuffers将两个32位UINT转换为一个JS编号,将其传递,然后将其转换回两个32位UINT。恢复的位是否与原始位相同,或者JS引擎是否允许随意更改NaN的位?换句话说,JS

在JavaScript中,NaN值可以在内部由一系列64位双精度表示。具体而言,任何具有以下按位表示的双精度:

x111 1111 1111 xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx
被解释为NaN。我的问题是:假设我使用ArrayBuffers将两个32位UINT转换为一个JS编号,将其传递,然后将其转换回两个32位UINT。恢复的位是否与原始位相同,或者JS引擎是否允许随意更改NaN的位?换句话说,JS数字可以用于无损存储64位吗?

ECMA-262第9版,2018年6月,(JavaScript要遵守的标准)在6.1.6中说“数字类型”:

…IEEE标准的9007199254740990(即253-2)不同的“非数字”值在ECMAScript中表示为单个特殊NaN值…在某些实现中,外部代码可能能够检测到各种非数字值之间的差异,但这种行为取决于实现;对于ECMAScript代码,所有NaN值彼此之间都无法区分

24.1.17“NumberToRawBytes(类型、值、isLittleEndian)”表示:

…如果值为NaN,则可以将rawBytes设置为选择IEEE 754-2008 binary64格式而非数字编码的任何实现。实现必须始终为每个实现选择相同的编码可区分的NaN值

在这个问题上,我看不到任何其他提到南的段落。一方面,24.1.17有效地告诉我们在将NaN转换为原始字节时必须保留NaN的位。然而,似乎没有其他任何东西告诉我们这些位必须在其他操作中保留。人们可能会推断这是目的,因为如果位可以通过任何其他操作任意更改,那么24.1.17中的这一要求将毫无用处。但我不会依赖JavaScript实现来实现这一点,因为我曾经向Java询问过NaN值的硬件依赖性,人们注意到一些CPU会默默地将“信令NaN”转换为“安静NaN”(设置安静NaN位)将NaN值加载到处理器寄存器时因此至少有一个位,即安静的NaN位,不能用于存储任意数据。

只要设置了安静的NaN位,使用其他位可能是安全的。但这里似乎仍然有实现依赖的空间,因此没有保证


这类问题就是为什么正常的语言操作避免做任何依赖于NaN的内部值的事情,而更喜欢将所有NaN视为“just NaN”。

最初的IEEE-754标准故意将NaN的位留给实现。它确实提供了一些提示,例如

您可以将创建NaN的原始内存地址放入其中


同时,算术有关于如何处理NaN的特定规则,而这与底部的位无关。我认为它甚至没有说明在添加两个N时应该做什么——保留其中一个的位,而不是组成另一组位。只是结果仍然是一个NaN。

我提出了一个有趣的想法。似乎至少Node.js会随意更改位,导致信息丢失。旁白:不是每个这样的位模式都代表一个NaN。如果第一个之后的所有x but都为零,则表示无穷大。