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


12

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

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

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


2
有趣的主意
Evert

1
我做了一个测试。似乎至少Node.js会随意更改位,从而导致信息丢失。
MaiaVictor

1
另外:并非每个这样的位模式都代表一个NaN。如果第一个之后的所有x buts均为零,则表示无穷大。
Eric Postpischil,

Answers:


6

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

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

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

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

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


1

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

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

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


0

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

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.