198

只是出于好奇。

数字似乎不太合乎逻辑typeof NaN。顺便说一句,就像NaN === NaNNaN == NaN返回 false 一样。这是 javascript 的特性之一,还是有原因?

编辑:感谢您的回答。不过,要吸引人并不是一件容易的事。阅读答案和维基,我理解得更多,但仍然像这样的句子

与 NaN 的比较始终返回无序结果,即使与自身进行比较也是如此。比较谓词是信令或非信令,信令版本表示此类比较的无效异常。等式和不等式谓词是无信号的,因此 x = x 返回 false 可用于测试 x 是否是安静的 NaN。

只是让我头晕目眩。如果有人可以将其翻译成人类(而不是数学家)可读的语言,我将不胜感激。

4

21 回答 21

120

NaN好吧,尽管有这样的事实,被称为“非数字”的东西被认为是数字,但仍然是数字类型,这似乎有点奇怪:-)

NaN只是意味着特定值不能在数字类型的限制内表示(尽管可以说所有数字都必须四舍五入以适应,但这NaN是一种特殊情况)。

一个特定NaN的不被认为等于另一个NaN,因为它们可能是不同的值。但是,NaN仍然是数字类型,就像 2718 或 31415。


至于你更新的问题,用外行的话来解释:

与 NaN 的比较始终返回无序结果,即使与自身进行比较也是如此。比较谓词是信令或非信令,信令版本表示此类比较的无效异常。等式和不等式谓词是无信号的,因此返回 false 的 x = x 可用于测试 x 是否是安静的 NaN。

所有这些意味着(分解为部分):

与 NaN 的比较始终返回无序结果,即使与自身进行比较也是如此。

基本上, aNaN不等于任何其他数字,包括 another NaN,甚至包括自身

比较谓词是信令或非信令,信令版本表示此类比较的无效异常。

尝试在 a 和另一个数字之间进行比较(小于、大于等)操作NaN可能会导致抛出异常(信号)或结果为 false(非信号或安静)。

等式和不等式谓词是无信号的,因此返回 false 的 x = x 可用于测试 x 是否是安静的 NaN。

相等测试(等于,不等于)永远不会发出信号,因此使用它们不会导致异常。如果您有一个常规数字x,那么x == x将永远是正确的。如果x是 a NaN,那么x == x永远是假的。它为您提供了一种NaN轻松(安静地)检测的方法。

于 2010-05-10T09:33:47.373 回答
64

这意味着不是一个数字。这不是 javascript 的特性,而是常见的计算机科学原理。

来自http://en.wikipedia.org/wiki/NaN

返回 NaN 的操作有以下三种:

以 NaN 作为至少一个操作数的操作

不确定的形式

  • 分割 0/0、∞/∞、∞/-∞、-∞/∞ 和 -∞/-∞
  • 乘法 0×∞ 和 0×−∞
  • 幂 1^∞
  • 加法 ∞ + (-∞)、(-∞) + ∞ 和等效减法。

具有复杂结果的实际操作:

  • 负数的平方根
  • 负数的对数
  • 90 度(或 π/2 弧度)的奇数倍的正切
  • 小于 -1 或大于 +1 的数的反正弦或余弦。

所有这些值可能都不相同。NaN 的一个简单测试是测试value == value是否为假。

于 2010-05-10T09:35:43.503 回答
22

ECMAScript (JavaScript) 标准指定IEEE 754浮点数,其中包括Numbers一个可能的值。NaN

ECMA 262 5e 第 4.3.19 节:数值

对应于双精度 64 位二进制格式 IEEE 754 值的原始值。

ECMA 262 5e 第 4.3.23 节:NaN

作为 IEEE 754“非数字”值的数字值。

维基百科上的IEEE 754

IEEE 浮点算术标准是由电气和电子工程师协会制定的技术标准,是浮点计算最广泛使用的标准 [...]

该标准定义

  • 算术格式:二进制和十进制浮点数据集,由有限数(包括有符号零和次正规数)、无穷大和特殊的“非数字”值 (NaN)组成

[...]

于 2011-07-13T12:13:17.187 回答
9

typeof NaN返回'number',因为:

  • ECMAScript 规范说 Number 类型包括 NaN:

    4.3.20 号码类型

    所有可能的数字值的集合,包括特殊的“非数字”(NaN) 值、正无穷大和负无穷大

  • 所以typeof相应地返回:

    11.4.3 typeof 运算符

    产生式 UnaryExpression : typeof UnaryExpression的评估如下:

    1. val为计算UnaryExpression的结果。
    2. 如果Type ( val ) 是Reference,那么
      1. 如果IsUnresolvableReference ( val ) 为true,则返回"undefined"
      2. valGetValue ( val )。
    3. 根据表 20 返回由Type ( val ) 确定的字符串。

                    Table 20 — typeof Operator Results
    ==================================================================
    |        Type of val         |              Result               |
    ==================================================================
    | Undefined                  | "undefined"                       |
    |----------------------------------------------------------------|
    | Null                       | "object"                          |
    |----------------------------------------------------------------|
    | Boolean                    | "boolean"                         |
    |----------------------------------------------------------------|
    | Number                     | "number"                          |
    |----------------------------------------------------------------|
    | String                     | "string"                          |
    |----------------------------------------------------------------|
    | Object (native and does    | "object"                          |
    | not implement [[Call]])    |                                   |
    |----------------------------------------------------------------|
    | Object (native or host and | "function"                        |
    | does implement [[Call]])   |                                   |
    |----------------------------------------------------------------|
    | Object (host and does not  | Implementation-defined except may |
    | implement [[Call]])        | not be "undefined", "boolean",    |
    |                            | "number", or "string".            |
    ------------------------------------------------------------------
    

此行为符合IEEE 浮点算术标准 (IEEE 754)

4.3.19 数值

对应于双精度 64 位二进制格式 IEEE 754 值的原始值

4.3.23 南

数字值,它是 IEEE 754“非数字”值

8.5 数字类型

Number 类型正好有 18437736874454810627(即 2 53 −2 64 +3)个值,代表二进制浮点算术的 IEEE 标准中指定的双精度 64 位格式 IEEE 754 值,除了 9007199254740990 (也就是说,IEEE 标准的 2 53 -2) 个不同的“非数字”值在 ECMAScript 中表示为单个特殊的NaN值。(请注意,NaN值是由程序表达式生成的NaN。)

于 2015-01-10T20:59:32.943 回答
6

NaN != NaN因为它们不需要相同的非数字。因此这很有意义......还有为什么浮点数的 +0.00 和 -0.00 都不相同。四舍五入可能会导致它们实际上不为零。

至于 typeof,这取决于语言。大多数语言会说 NaN 是浮点数、双精度数或数字,具体取决于它们的分类方式……我知道没有语言会说这是未知类型或空值。

于 2010-05-10T09:33:43.240 回答
5

NaN 是一个有效的浮点值(http://en.wikipedia.org/wiki/NaN

和 NaN === NaN 是假的,因为它们不一定是相同的非数字

于 2010-05-10T09:35:48.523 回答
4

NaN代表非数字。它是数值数据类型(通常是浮点类型,但不总是)的值,表示无效操作的结果,例如除以零。

虽然它的名字说它不是数字,但用来保存它的数据类型是数字类型。所以在 JavaScript 中,询问NaN将返回的数据类型numberalert(typeof(NaN))清楚地表明)。

于 2011-07-13T12:12:28.330 回答
2

Javascript 使用 NaN 来表示它遇到的任何无法通过其规范以任何其他方式表示的东西。这并不意味着它不是一个数字。这只是描述相遇的最简单的方式。NaN 表示它或引用它的对象不能用 javascript 以任何其他方式表示。出于所有实际目的,它是“未知的”。作为“未知”,它不能告诉你它是什么,即使它是它自己。它甚至不是分配给它的对象。它只能告诉你它不是什么,而不是或虚无只能用编程语言在数学上描述。由于数学是关于数字的,javascript 将虚无表示为 NaN。这并不意味着它不是一个数字。这意味着我们无法以任何其他有意义的方式阅读它。这就是为什么它可以' t 甚至等于它自己。因为它没有。

于 2011-12-22T09:21:47.303 回答
2

一个更好的名称NaN,更准确地描述其含义,更少混淆,将是一个数字例外。它实际上是另一种伪装成具有原始类型的异常对象(通过语言设计),同时在错误的自我比较中它不被视为原始类型。混乱从何而来。并且只要语言“不会下定决心”在适当的异常对象原始数字之间进行选择,混乱就会继续存在。

NaN臭名昭著的对自身不相等,这==两者===都是令人困惑的设计的表现,迫使这个异常对象成为原始类型。这打破了基元由其值唯一确定的基本原则。如果NaN更愿意被视为例外(其中可以有不同的种类),那么它不应该被“出售”为原始的。如果它想要是原始的,那么这个原则就必须成立。只要它被破坏,就像我们在 JavaScript 中那样,并且我们无法在两者之间做出真正的决定,那么导致每个相关人员不必要的认知负担的混乱就会继续存在。但是,只需在两者之间做出选择,就很容易解决这个问题:

  • 要么创建NaN一个特殊的异常对象,其中包含有关异常如何产生的有用信息,而不是将这些信息作为当前实现的内容丢弃,从而导致更难调试的代码;
  • 或者创建NaN一个原始类型的实体number(可以不那么容易混淆地称为“数字”),在这种情况下它应该等于它自己并且不能包含任何其他信息;后者显然是次要的选择。

NaN强制输入类型的唯一可以想象的优点number是能够将其放回任何数值表达式中。然而,这使它成为一个脆弱的选择,因为任何包含的数值表达式的结果NaN要么是NaN,要么导致不可预测的结果,例如NaN < 0评估为false,即返回boolean而不是保持异常。

即使“事情就是这样”,也没有什么能阻止我们为自己做出明确的区分,以帮助我们的代码更可预测和更容易调试。在实践中,这意味着识别这些异常并将它们作为异常处理。不幸的是,这意味着更多的代码,但希望能被 Flowtype 的 TypeScript 等工具减轻。

然后我们有凌乱的安静与嘈杂的信号NaN区别。这实际上是关于如何处理异常,而不是异常本身,与其他异常没有什么不同。

同样,Infinity和是在实线的延伸中产生的数字类型+Infinity元素,但它们不是实数。在数学上,它们可以由收敛于或的实数序列表示。+-Infinity

于 2016-05-17T03:37:19.650 回答
1

考虑 NAN 的最佳方式是它不是一个已知的数字。这就是为什么 NAN != NAN 因为每个 NAN 值都代表一些唯一的未知数。NAN 是必要的,因为浮点数的值范围有限。在某些情况下,舍入会发生在低位丢失的情况下,这会导致看起来像 1.0/11*11 != 1.0 这样的废话。真正更大的值是无穷大的 NAN 就是一个很好的例子。

鉴于我们只有十根手指,任何显示大于 10 的值的尝试都是不可能的,这意味着这些值必须是 NAN,因为我们已经失去了这个大于 10 值的真实值。浮点值也是如此,其中的值超出了浮点数的限制。

于 2010-05-10T12:25:09.653 回答
1

如果使用 jQuery,我更喜欢isNumeric检查类型:

console.log($.isNumeric(NaN));  // returns false
console.log($.type(NaN));       // returns number

http://api.jquery.com/jQuery.isNumeric/

于 2013-07-19T18:53:03.407 回答
1

NaN 仍然是数字类型,但它表示的值不能表示有效数字。

于 2011-07-13T12:12:34.310 回答
1

因为 NaN 是数字数据类型。

于 2011-07-13T12:12:54.553 回答
1

NaN从类型的角度来看是一个数字,但不是像 1、2 或 329131 这样的普通数字。“非数字”这个名称是指表示的值是特殊的,并且是关于 IEEE 格式规范域的事实,而不是javascript 语言域。

于 2011-07-13T12:13:29.967 回答
1

这仅仅是因为NaN它是 JS 中 Number 对象的一个​​属性,它与它是一个数字无关。

于 2010-05-10T09:35:09.350 回答
0

Javascript 只有一种数值数据类型,即标准的 64 位双精度浮点数。一切都是双重的。NaN 是 double 的特殊值,但它仍然是 double。

所做parseInt的只是将您的字符串“转换”为数字数据类型,因此结果始终为“数字”;仅当原始字符串不可解析时,其值为 NaN。

于 2011-07-13T12:12:11.013 回答
0

我们可以说 NaN 是一个特例对象。在这种情况下,NaN 的对象表示一个没有数学意义的数字。数学中还有一些其他特殊情况对象,例如 INFINITE 等。

你仍然可以用它做一些计算,但这会产生奇怪的行为。

更多信息在这里: http: //www.concentric.net/~ttwang/tech/javafloat.htm(基于java,不是javascript)

于 2011-07-13T12:16:01.430 回答
0

你必须喜欢 Javascript。它有一些有趣的小怪癖。

http://wtfjs.com/page/13

如果您停下来从逻辑上解决它们,或者如果您对数论有所了解,则可以解释大多数这些怪癖,但是如果您不了解它们,它们仍然可以抓住您。

顺便说一句,我建议阅读http://wtfjs.com/的其余部分——还有比这个更有趣的怪癖!

于 2011-07-13T12:16:13.163 回答
0

NaN 的值实际上是 Number.NaN,因此当您询问它是否是数字时,它会说是。您通过使用 isNaN() 调用做了正确的事情。

作为信息,NaN 也可以通过对未定义的数字的操作返回,例如除以零或负数的平方根。

于 2011-07-13T12:19:22.620 回答
-2

它是数字类型的特殊值,如 POSITIVE_INFINITY

为什么?按设计

于 2011-07-13T12:12:20.030 回答
-2

一个例子

想象一下,我们正在将一个字符串转换为一个数字:

Number("string"); // returns NaN

我们将数据类型更改为数字,但它的值不是数字!

于 2019-04-10T14:24:44.010 回答