首页 > 解决方案 > 用初学者的话来说,NaN(非数字)是什么?

问题描述

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

主要问题:

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

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

  1. 什么是导致 NaN 值的操作?

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

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

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

  5. 为什么 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

堆栈溢出:

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

在 Java 中,NaN 是什么意思?

对于 IEEE754 NaN 值返回 false 的所有比较的基本原理是什么?

JavaScript中的(内置)方法来检查字符串是否为有效数字

JavaScript:什么是 NaN、对象或原语?

不是数字 (NaN)

C++ 的问题:

安静 NaN 和信令 NaN 有什么区别?

在 C++ 中检查双精度(或浮点数)是否为 NaN

为什么使用英特尔 C++ 编译器时 NaN - NaN == 0.0?

IND和NAN号有什么区别


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

标签: mathfloating-pointnanieee-754

解决方案


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

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

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

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

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

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

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

什么是导致 NaN 值的操作?

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

  1. 取负数的对数。
  2. 取负数的平方根。
  3. 从无穷大中减去无穷大。
  4. 对 执行任何算术运算NaN

NaN然而,有些操作即使在数学上是未定义的,也不会产生。例如,将正数除以零会得到正无穷大,即使这不是数学定义的。这样做的原因是,如果当 y 从正方向接近零时,将 x / y 设为正 x 的极限,则值会无限增长。

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

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

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

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

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

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

有关如何实际存储数字以及这在实践中意味着什么的更多信息,请查看传奇指南“每个程序员应该了解的浮点运算知识”

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

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

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

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

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

为什么 NaN 不等于不定?

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

希望这可以帮助!


推荐阅读