用初学者的话来说,NaN(非数字)是啥? [关闭]

Posted

技术标签:

【中文标题】用初学者的话来说,NaN(非数字)是啥? [关闭]【英文标题】:What is NaN (Not a Number) in the words of a beginner? [closed]用初学者的话来说,NaN(非数字)是什么? [关闭] 【发布时间】:2020-04-07 15:24:06 【问题描述】:

我仍然不明白 NaN 或(不是实数的数字)到底是什么。

主要问题:

    究竟什么是 NaN 值或 NaN(用非数学教授的话来说)?

此外,我对整个情况有几个问题,这让我对理解 NaN 应该是什么感到不满,这不是回答我的主要问题所必需的,而是想要的:

    导致 NaN 值作为结果的操作是什么?

    为什么 0.0 / 0.0 的结果被声明为未定义?不应该是0吗?

    为什么任何数学运算的结果都不能用浮点数或整数表示?一个值怎么会是不可表示的?

    为什么负数的平方根不是实数?

    为什么 NaN 不等于不定?

我没有在整个互联网上找到任何可以理解的解释 NaN 对我来说是什么,包括在 Stack Overflow 上。


无论如何,我想提供我的研究作为地点的链接,我已经扫描以找到我的问题的可理解答案,即使某些链接在其他编程语言中指向相同的问题,但没有给我想要的明确总资料:

***:

https://en.wikipedia.org/wiki/NaN

https://en.wikipedia.org/wiki/IEEE_754

其他:

http://foldoc.org/Not-a-Number

https://www.youtube.com/watch?v=HN_UmxIVS6M

https://www.youtube.com/watch?v=9EsHjXftO7s

堆栈溢出:

其他语言的类似或相同问题(我提供它们,只要我认为理解的基础非常相似,如果不相同):

In Java, what does NaN mean?

What is the rationale for all comparisons returning false for IEEE754 NaN values?

(Built-in) way in javascript to check if a string is a valid number

JavaScript: what is NaN, Object or primitive?

Not a Number (NaN)

关于 C++ 的问题:

What is difference between quiet NaN and signaling NaN?

Checking if a double (or float) is NaN in C++

Why does NaN - NaN == 0.0 with the Intel C++ Compiler?

What is the difference between IND and NAN numbers


感谢您提供所有有用的答案和 cmets。

【问题讨论】:

Why is the result of 0.0 / 0.0 declared as undefined? Shouldn´t it be 0? 为什么应该是0?什么东西除以0?不是 0。 请只问一个问题 另外,您的大部分问题都应该在数学 QA 网站上提出,而不是在编程网站上提出。 @tkausl lim x->0 x*x / x = 0 @ThomasSablik 为什么选择x*x 作为分子?您可以使用这样的限制和适当的分子生成任何结果。 【参考方案1】:

浮点数被编码为位模式,但并非所有可用的位模式(对于给定的位数)都被使用,因此有些位模式不编码任何浮点数。如果找到此类模式,它们将被视为/显示为 NaN。

【讨论】:

NaN 的存在不仅仅是因为 IEEE-754 的设计者忽略了使用所有可用的位模式。它们的存在是有意的、设计的和有目的的。模式不仅仅是“找到”的;它们是通过初始化故意设置的,或者是指定的操作结果。【参考方案2】:

数学数字系统包含一组值。例如,正整数是 0、1、2、3、4 等。负整数是 -1、-2、-3、-4 等(也可能是 -0,取决于你的数学分支)。

在计算机领域,浮点数还具有“无穷大”和“非数字”等概念。这就像数字的“NULL”。它的意思是“浮点值不代表数学意义上的数字”。

程序员有一个float,但他们不想给出数字值时,它们很有用,并且浮点标准也使用它们来表示“无效”的结果操作。

例如,您可以通过将零除以零来获得 NaN,这是我所知道的任何数学分支中没有任何意义的操作:您如何在 no 人?。

(如果您尝试对没有 NaN 或无穷大概念的整数执行此操作,则会得到一个 [terribly-named] “浮点异常”;换句话说,您的程序将崩溃。)

在Wikipedia's article about NaN 上阅读更多信息,它几乎可以回答您的所有问题。

【讨论】:

【参考方案3】:

有关摘要,您可以查看wikiedia page:

在计算中,NaN,代表非数字,是数字的成员 可以解释为未定义值的数据类型或 无法表示,尤其是在浮点运算中。系统的 IEEE 754 浮点标准在 1985 年,连同其他非有限量的表示 比如无穷大。

在实际方面,我会指出这一点:

如果 x 或 y 是 NaN 浮点数:则表达式如下:

x<y
x<=y
x>y
x>=y
x==x

总是假的。不过,

x!=x

将为 true,这是一种检查 x 是否为 NaN 的方法(请参阅 std::isnan)。

另一个说明是,当数值计算中出现一些 NaN 时,您可能会观察到 大幅减速(这也可能是调试时的提示)

Intel CPU 上的 NaN 操作可能会产生异常 调用微码,因此相对减速可能变化很大 与 CPU 型号。

例如见NaN slowdown

【讨论】:

【参考方案4】:

您在这里提出了一系列很好的问题。这是我试图解决每个问题的尝试。

究竟什么是 NaN 值或 NaN(用非数学教授的话来说)?

假设您正在处理实数 - 1、π、e、-137、6.626 等数字。在实数领域,通常可以进行一些操作执行,但有时没有定义的结果。例如,让我们看一下对数。您可以取许多实数的对数:例如,ln e = 1,而 ln 10 约为 2.3。但是,从数学上讲,负数的对数没有定义。也就是说,我们不能取 ln (-4) 并返回一个实数。

所以现在,让我们跳到编程领域。想象一下,你正在编写一个程序来计算一个数字的对数,并且用户希望你以某种方式除以一个负数的对数。应该怎么办?

这个问题有很多合理的答案。您可以让操作引发异常,这在 Python 等某些语言中完成。

然而,在硬件层面(由设计 IEEE-754 标准的人)做出的决定是为程序员提供第二个选择。与其让程序崩溃,不如让操作产生一个值,表示“你想让我做一些不可能的事情,所以我报告一个错误”。完成此操作的方法是让运算产生特殊值 NaN(“非数字”),这表明在您的计算中,您尝试执行数学上未定义的运算。

这种方法有一些优点。在许多科学计算设置中,代码执行一系列长计算,定期生成可能感兴趣的中间结果。通过让未定义的操作产生 NaN 作为结果,程序员可以编写代码,按照他们的意愿进行数学运算,然后在代码中引入特定点,他们将测试操作是否成功或不。从那里,他们可以决定做什么。与触发异常或彻底崩溃程序相比,这意味着程序员要么需要保护每一系列可能失败的浮点操作,要么必须自己手动测试。这是关于哪个选项更好的判断调用,这就是您可以启用或禁用浮点 NaN 行为的原因。

导致 NaN 值作为结果的操作是什么?

有很多方法可以从操作中获取NaN 结果。这是一个采样器,虽然这不是一个详尽的列表:

    取负数的日志。 取负数的平方根。 从无穷大中减去无穷大。 对NaN 执行任何算术运算。

然而,有些运算不会产生NaN,即使它们在数学上是未定义的。例如,将正数除以零会得到正无穷大,即使这不是数学定义的。这样做的原因是,如果当 y 从正方向趋近于零时,对于正 x 取 x / y 的限制,则值会无限增长。

为什么 0.0 / 0.0 的结果声明为未定义?不应该是0吗?

这更像是一道数学题。这与限制的工作方式有关。让我们考虑如何定义 0 / 0。一种选择是这样说:如果我们查看表达式 0 / x 并在 x 接近零时取极限,那么我们会在每个点看到 0,所以极限应该为零。另一方面,如果我们查看表达式 x / x 并在 x 接近 0 时取极限,我们会在每个点看到 1,因此极限应该是 1。这是有问题的,因为我们希望 0 / 0 的值与您在评估这些表达式中的任何一个时发现的值一致,但我们无法选择一个有意义的固定值。结果,0 / 0 的值被评估为NaN,表明这里没有明确的值可分配。

为什么任何数学运算的结果都不能用浮点数或整数表示?一个值怎么会是不可表示的?

这与 IEEE-754 浮点数的内部有关。直观地说,这归结为一个简单的事实:

    实数有无限多,其中有无限多的非重复小数是无限长的,但是 您的计算机内存有限。

因此,存储任意实数可能需要存储无限长的数字序列,而我们的有限内存计算机无法做到这一点。因此,我们有浮点数存储近似值的实数并不是非常庞大,而无法表示值的原因是我们只是存储了近似值。

有关数字实际存储方式的更多信息,以及这在实践中的含义,请查看传奇指南"What Every Programmer Should Know About Floating-Point Arithmetic"

为什么负数的平方根不是实数?

我们以 √(-1) 为例。想象这是一个实数 x;也就是说,假设 x = √(-1)。平方根的概念是,它是一个数字,如果与自身相乘,则返回取平方根的数字。

那么... x 是多少?我们知道 x ≠ 0,因为 02 = 0 不是 -1。我们也知道 x 不可能是正数,因为任何正数乘以自身都是正数。而且我们知道x不可能是负数,因为任何负数乘以自身都是正数。

我们现在有一个问题。无论这个 x 是什么,它都必须不是正数,不是零,也不是负数。这意味着它不是一个实数。

您可以通过引入数字 i 将实数推广到复数,其中 i2 = -1。请注意,由于上述原因,没有实数会这样做。

为什么 NaN 不等于不定?

“不定”和“不管它是什么,它都不是一个实数”是有区别的。例如,0 / 0 可以说是不确定的,因为根据你接近 0 / 0 的方式,你可能会得到 0、1 或其他东西。另一方面,√(-1) 被完美地定义为复数(假设我们有 √(-1) 返回 i 而不是 -i),所以问题不在于“这是不确定的”作为“它有一个值,但该值不是实数。”

希望这会有所帮助!

【讨论】:

设计 IEEE 754 的人并没有决定让操作返回 NaN。他们决定给程序员选择。浮点异常可以被捕获或产生默认结果。这旨在成为程序员的选择,但 IEEE 754 的不完整实现可能无法提供该选择。此类实现的实现者负责决定生成 NaN 而不是陷阱,而不是 IEEE-754 委员会。 @EricPostpischil 感谢您的更正!答案已更新。 @templatetypedef 非常感谢,这就是我想要的答案。我需要一段时间来详细介绍所有事情。非常感谢。

以上是关于用初学者的话来说,NaN(非数字)是啥? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

初学者 Drupal 用户最常见的陷阱是啥? [关闭]

c语言中mincost=INF是啥意思

输入包含 NaN、无穷大或对于 dtype('float64') 来说太大的值。解决办法是啥

在 df agg() 函数中计算 NaN 的最 Pythonic 方法是啥?

缺少基于非数字(NaN)的概念[重复]

js的if语句判断条件到底是啥情况