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

时间:2019-11-07 20:55:27

标签: javascript ieee-754

在JavaScript中,NaN值可由内部广泛的64位double表示。具体来说,具有以下按位表示形式的任何double:

plot

被解释为NaN。我的问题是:假设我使用ArrayBuffers将两个32位uint强制转换为一个JS Number,将其传递,然后将其强制转换为两个32位uint。恢复的位是否将与原始位相同,还是允许JS引擎随意更改NaN的位?换句话说,可以使用JS数字来无损地存储64位吗?

3 个答案:

答案 0 :(得分:6)

ECMA-262 9 版,2018年6月(JavaScript旨在遵循的标准)在6.1.6“数字类型”中表示:

  

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

24.1.17“ NumberToRawBytes(类型,值,isLittleEndian)”说:

  

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

我没有看到其他提及NaN的文章阐明了这个问题。一方面,24.1.17有效地告诉我们将NaN转换为原始字节时必须保留NaN的位。但是,似乎没有什么可以告诉我们在其他操作中必须保留这些位。可能会推断出这是目的,因为如果可以通过任何其他操作任意更改这些位,则24.1.17中的这一要求将毫无用处。但是我不会依靠JavaScript实现来实现此目的。

答案 1 :(得分:1)

我曾经问过a question Java语言有关NaN值的硬件依赖性,并且注意到有些CPU会静默地将“信号NaN”转换为“安静NaN”(设置安静的NaN位)。当将NaN值加载到处理器寄存器中时。 因此,至少有一个位(安静的NaN位)不能用于存储任意数据。

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

这种问题就是为什么正常的语言操作会避免做任何依赖于NaN内部值的事情,而宁愿将所有NaN都视为“正好是NaN”。

答案 2 :(得分:0)

原始的IEEE-754标准故意将NaN的各个部分留给实现。它确实提供了提示,例如

您可以输入创建NaN的原始内存地址。

与此同时,算术对于NaN的处理有特定的规则,而与底部的位无关。我什至不认为添加两个NaN时该怎么做-保留其中一个位而不是组成另一组位。只是结果必须仍然是NaN。