Javascript 为什么 typeof NaN 返回“数字”?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2801601/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 01:59:24  来源:igfitidea点击:

Why does typeof NaN return 'number'?

javascriptnan

提问by KooiInc

Just out of curiosity.

只是出于好奇。

It doesn't seem very logical that typeof NaNis number. Just like NaN === NaNor NaN == NaNreturning false, by the way. Is this one of the peculiarities of javascript, or would there be a reason for this?

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

Edit: thanks for your answers. It's not an easy thing to get ones head around though. Reading answers and the wiki I understood more, but still, a sentence like

编辑:感谢您的回答。然而,让人们转过头来并不是一件容易的事情。阅读答案和维基我了解更多,但仍然是这样的一句话

A comparison with a NaN always returns an unordered result even when comparing with itself. The comparison predicates are either signaling or non-signaling, the signaling versions signal an invalid exception for such comparisons. The equality and inequality predicates are non-signaling so x = x returning false can be used to test if x is a quiet NaN.

与 NaN 的比较总是返回一个无序的结果,即使与它自己比较时也是如此。比较谓词是信令或非信令,信令版本为此类比较发出无效异常信号。等式和不等式谓词是无信号的,因此返回 false 的 x = x 可用于测试 x 是否为安静的 NaN。

just keeps my head spinning. If someone can translate this in human (as opposed to, say, mathematician) readable language, I would be gratefull.

只是让我的头旋转。如果有人可以用人类(而不是数学家)可读的语言来翻译它,我将不胜感激。

采纳答案by Charles Beattie

It means Not a Number. It is not a peculiarity of javascript but common computer science principle.

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

From http://en.wikipedia.org/wiki/NaN:

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

There are three kinds of operation which return NaN:

Operations with a NaN as at least one operand

Indeterminate forms

  • The divisions 0/0, ∞/∞, ∞/?∞, ?∞/∞, and ?∞/?∞
  • The multiplications 0×∞ and 0×?∞
  • The power 1^∞
  • The additions ∞ + (?∞), (?∞) + ∞ and equivalent subtractions.

Real operations with complex results:

  • The square root of a negative number
  • The logarithm of a negative number
  • The tangent of an odd multiple of 90 degrees (or π/2 radians)
  • The inverse sine or cosine of a number which is less than ?1 or greater than +1.

返回 NaN 的操作有 3 种:

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

不确定形式

  • 除法 0/0、∞/∞、∞/?∞、?∞/∞ 和?∞/?∞
  • 0×∞ 和 0×?∞ 的乘法
  • 幂 1^∞
  • 加法∞ + (?∞)、(?∞) + ∞ 和等效减法。

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

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

All these values may not be the same. A simple test for a NaN is to test value == valueis false.

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

回答by paxdiablo

Well, NaNis still a numeric type, despite the fact it actually stands for Not-A-Number :-)

嗯,NaN仍然是数字类型,尽管它实际上代表 Not-A-Number :-)

NaNjust means the specific value cannot be represented within the limitations of the numeric type (although that could be said for all numbers that have to be rounded to fit, but NaNis a special case).

NaN只是意味着无法在数字类型的限制范围内表示特定值(尽管对于必须四舍五入以适合的所有数字,但这NaN是一种特殊情况)。

A specific NaNis not considered equal to another NaNbecause they may be different values. However, NaNis still a number type, just like 2718 or 31415.

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



As to your updated question to explain in layman's terms:

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

A comparison with a NaN always returns an unordered result even when comparing with itself. The comparison predicates are either signalling or non-signalling, the signalling versions signal an invalid exception for such comparisons. The equality and inequality predicates are non-signalling so x = x returning false can be used to test if x is a quiet NaN.

与 NaN 的比较总是返回一个无序的结果,即使与它自己比较时也是如此。比较谓词是信令或非信令,信令版本为此类比较发出无效异常信号。等式和不等式谓词是无信号的,因此返回 false 的 x = x 可用于测试 x 是否为安静的 NaN。

All this means is (broken down into parts):

所有这些都意味着(分解成几个部分):

A comparison with a NaN always returns an unordered result even when comparing with itself.

与 NaN 的比较总是返回一个无序的结果,即使与它自己比较时也是如此。

Basically, a NaNis not equal to any other number, including another NaN, and even including itself.

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

The comparison predicates are either signalling or non-signalling, the signalling versions signal an invalid exception for such comparisons.

比较谓词是信令或非信令,信令版本为此类比较发出无效异常信号。

Attempting to do comparison (less than, greater than, and so on) operations between a NaNand another number can either result in an exception being thrown (signalling) or just getting false as the result (non-signalling or quiet).

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

The equality and inequality predicates are non-signalling so x = x returning false can be used to test if x is a quiet NaN.

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

Tests for equality (equal to, not equal to) are never signalling so using them will not cause an exception. If you have a regular number x, then x == xwill always be true. If xis a NaN, then x == xwill always be false. It's giving you a way to detect NaNeasily (quietly).

相等性测试(等于、不等于)永远不会发出信号,因此使用它们不会导致异常。如果你有一个普通的 number x,那么x == x将永远是真的。如果x是 a NaN,则x == x永远为假。它为您提供了一种NaN轻松(安静)检测的方法。

回答by Facebook Staff are Complicit

The ECMAScript (JavaScript) standard specifies that Numbersare IEEE 754floats, which include NaNas a possible value.

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

ECMA 262 5e Section 4.3.19: Number value

primitive value corresponding to a double-precision 64-bit binary format IEEE 754 value.

ECMA 262 5e 第 4.3.19 节:数值

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

ECMA 262 5e Section 4.3.23: NaN

Number value that is a IEEE 754 "Not-a-Number" value.

ECMA 262 5e 第 4.3.23 节:NaN

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

IEEE 754on Wikipedia

The IEEE Standard for Floating-Point Arithmetic is a technical standard established by the Institute of Electrical and Electronics Engineers and the most widely used standard for floating-point computation [...]

The standard defines

  • arithmetic formats: sets of binary and decimal floating-point data, which consist of finite numbers (including signed zeros and subnormal numbers), infinities, and special "not a number" values (NaNs)

[...]

维基百科上的IEEE 754

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

该标准定义了

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

[...]

回答by Oriol

typeof NaNreturns 'number'because:

typeof NaN返回,'number'因为:

  • ECMAScript spec says the Number type includes NaN:

    4.3.20 Number type

    set of all possible Number values including the special “Not-a-Number” (NaN) values, positive infinity, and negative infinity

  • So typeofreturns accordingly:

    11.4.3 The typeof Operator

    The production UnaryExpression: typeofUnaryExpressionis evaluated as follows:

    1. Let valbe the result of evaluating UnaryExpression.
    2. If Type(val) is Reference, then
      1. If IsUnresolvableReference(val) is true, return "undefined".
      2. Let valbe GetValue(val).
    3. Return a String determined by Type(val) according to Table 20.

                    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".            |
    ------------------------------------------------------------------
    
  • ECMAScript 规范说 Number 类型包括 NaN:

    4.3.20 号码类型

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

  • 所以相应地typeof返回:

    11.4.3 运算符的类型

    产生式UnaryExpression: typeofUnaryExpression的计算方式如下:

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

                    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".            |
    ------------------------------------------------------------------
    

This behavior is in accordance with IEEE Standard for Floating-Point Arithmetic (IEEE 754):

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

4.3.19 Number value

primitive value corresponding to a double-precision 64-bit binary format IEEE 754 value

4.3.23 NaN

number value that is a IEEE 754 “Not-a-Number” value

8.5 The Number Type

The Number type has exactly 18437736874454810627 (that is, 253?264+3) values, representing the double-precision 64-bit format IEEE 754 values as specified in the IEEE Standard for Binary Floating-Point Arithmetic, except that the 9007199254740990 (that is, 253?2) distinct “Not-a-Number” values of the IEEE Standard are represented in ECMAScript as a single special NaNvalue. (Note that the NaNvalue is produced by the program expression NaN.)

4.3.19 数值

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

4.3.23 南

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

8.5 号码类型

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

回答by Charles Ma

NaN is a valid floating point value (http://en.wikipedia.org/wiki/NaN)

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

and NaN === NaN is false because they're not necessarily the same non-number

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

回答by Cine

NaN != NaNbecause they are not necessary the SAME non-number. Thus it makes a lot of sense... Also why floats have both +0.00 and -0.00 that are not the same. Rounding may do that they are actually not zero.

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

As for typeof, that depends on the language. And most languages will say that NaN is a float, double or number depending on how they classify it... I know of no languages that will say this is an unknown type or null.

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

回答by Joachim Sauer

NaNstands for Not a Number. It is a value of numeric data types (usually floating point types, but not always) that represents the result of an invalid operation such as dividing by zero.

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

Although its names says that it's not a number, the data type used to hold it is a numeric type. So in JavaScript, asking for the datatype of NaNwill return number(as alert(typeof(NaN))clearly demonstrates).

虽然它的名字说它不是数字,但用来保存它的数据类型是数字类型。因此,在 JavaScript 中,要求NaN将返回的数据类型number(正如alert(typeof(NaN))清楚地演示的那样)。

回答by Louis

Javascript uses NaN to represent anything it encounters that can't be represented any other way by its specifications. It does not mean it is not a number. It's just the easiest way to describe the encounter. NaN means that it or an object that refers to it could not be represented in any other way by javascript. For all practical purposes, it is 'unknown'. Being 'unknown' it cannot tell you what it is nor even if it is itself. It is not even the object it is assigned to. It can only tell you what it is not, and not-ness or nothingness can only be described mathematically in a programming language. Since mathematics is about numbers, javascript represents nothingness as NaN. That doesn't mean it's not a number. It means we can't read it any other way that makes sense. That's why it can't even equal itself. Because it doesn't.

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

回答by Dmitri Zaitsev

A better name for NaN, describing its meaning more precisely and less confusingly, would be a numerical exception. It is really another kind of exception object disguised as having primitive type (by the language design), where at the same it is not treated as primitive in its false self-comparison. Whence the confusion. And as long as the language "will not make its mind" to choose between proper exception objectand primitive numeral, the confusion will stay.

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

The infamous non-equality of NaNto itself, both ==and ===is a manifestation of the confusing design forcing this exception object into being a primitive type. This breaks the fundamental principle that a primitive is uniquely determined by its value. If NaNis preferred to be seen as exception (of which there can be different kinds), then it should not be "sold" as primitive. And if it is wanted to be primitive, that principle must hold. As long as it is broken, as we have in JavaScript, and we can't really decide between the two, the confusion leading to unnecessary cognitive load for everyone involved will remain. Which, however, is really easy to fix by simply making the choice between the two:

臭名昭著的非平等NaN于本身,既=====是混淆设计迫使此异常对象形成了一个基本类型的体现。这打破了原语由其值唯一确定的基本原则。如果NaN更喜欢将其视为例外(其中可以有不同种类),则不应将其作为原始“出售”。如果它是原始的,那么这个原则必须成立。只要它被破坏,就像我们在 JavaScript 中那样,并且我们无法真正在两者之间做出决定,那么导致所有相关人员不必要的认知负担的混乱就会继续存在。然而,通过简单地在两者之间做出选择,真的很容易解决:

  • either make NaNa special exception object containing the useful information about how the exception arose, as opposed to throwing that information away as what is currently implemented, leading to harder-to-debug code;
  • or make NaNan entity of the primitive type number(that could be less confusingly called "numeric"), in which case it should be equal to itself and cannot contain any other information; the latter is clearly an inferior choice.
  • 要么创建NaN一个特殊的异常对象,其中包含有关异常如何产生的有用信息,而不是将该信息作为当前实现的内容扔掉,从而导致更难调试代码;
  • 或者创建NaN一个原始类型的实体number(可以不那么混淆地称为“数字”),在这种情况下,它应该等于自身并且不能包含任何其他信息;后者显然是次等选择。

The only conceivable advantage of forcing NaNinto numbertype is being able to throw it back into any numerical expression. Which, however, makes it brittle choice, because the result of any numerical expression containing NaNwill either be NaN, or leading to unpredictable results such as NaN < 0evaluating to false, i.e. returning booleaninstead of keeping the exception.

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

And even if "things are the way they are", nothing prevents us from making that clear distinction for ourselves, to help make our code more predictable and easierly debuggable. In practice, that means identifying those exceptions and dealing with them as exceptions. Which, unfortunately, means more code but hopefully will be mitigated by tools such as TypeScript of Flowtype.

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

And then we have the messy quiet vs noisy aka signalling NaNdistinction. Which really is about how exceptions are handled, not the exceptions themselves, and nothing different from other exceptions.

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

Similarly, Infinityand +Infinityare elements of numeric typearising in the extension of the real linebut they are not real numbers. Mathematically, they can be represented by sequences of real numbers converging to either +or -Infinity.

类似地,Infinity+Infinity在实线延伸中出现的数字类型元素,但它们不是实数。在数学上,它们可以由收敛到或的实数序列表示。+-Infinity

回答by BenM

Because NaN is a numeric data type.

因为 NaN 是数字数据类型。