【问题标题】:Divide by Zero: Infinite, NaN, or Zero Division Error? [closed]除以零:无限、NaN 或零除法误差? [关闭]
【发布时间】:2011-07-03 15:34:04
【问题描述】:

为什么1/0 == Inf 不是在所有语言中都有?这不是数学上最正确的反应吗?

我熟悉的所有语言都能够同时表达 Infinite 和 NaN 值,那么为什么他们会选择抛出错误或返回 NaN 呢?仅仅是为了让科学应用程序开发人员的生活更加艰难吗? ;-)

更新:我们或许应该关闭这个问题,因为我错误地认为 Java 中的 1f/0f == Float.NaN。但我错了:它确实正确地返回了Float.Infinity。那是我的主要困惑。某些语言会抛出错误这一事实是可以理解的,只要没有语言返回 NaN。

【问题讨论】:

  • 1/0 总是返回 Infinite,并可能引发浮点异常。 0/0 返回 NaN,并可能引发浮点异常。
  • @Tim Nordenfur:参见 IEEE 754 §7.1 和 §7.2(除以有限非零数和除数零 → 除以零陷阱或正确签名的 INFINITY;0/0 → 无效操作陷阱或安静的 NaN)。
  • 1/0 == Infinity 是一个经典的数学拖钓问题。我咬牙回答,但这个问题真的会惹麻烦。
  • @Steven 但这不是一个数学网站,大多数编程语言实际上确实这样处理它,尽管你的数学严谨,但你对拖钓的指责并不是很建设性的。如果没有你坚持这个事实,你的答案会好很多。
  • 哎呀....不。这绝对是最错误的回应!!!

标签: math programming-languages divide-by-zero


【解决方案1】:

除了 1 / 0 == inf 在数学上非常有问题之外,它在大多数编程语言中不起作用的简单原因是 1 / 0 几乎普遍地执行 整数除法 (有例外)。

结果是一个整数,根本无法将“无穷大”编码为整数。有浮点数,这就是为什么在大多数语言中浮点除法实际上会产生无限值。

对于 NaN 也是如此:虽然 IEEE 浮点标准定义了表示 NaN 值的位模式,但整数没有这样的值;因此,这些值根本不能表示为整数。

【讨论】:

  • 这是唯一一个费心解释黑白整数和浮点数差异的答案。
【解决方案2】:

这不是数学上最正确的回答吗?

不,因为在数学中,除以零是未定义的,并且无穷大通常不是一个值(或不是单个值)。

并非所有语言/库都返回 NaN 的原因是 (a) 零除通常是程序员错误的结果,因为它根本不应该出现在严格的数学算法中,并且 (b) 处理器可能会处理它通过进入异常状态,因此转换为 NaN 将需要处理此类状态,这意味着除法变得比现在更昂贵(与求和相比)。

【讨论】:

  • 其实在非标准分析中,除以零是未定义的。还有许多数学分支都有无穷大的定义,通常是许多无穷大。
【解决方案3】:

虽然1 / n 的极限会随着 n 接近零(从正方向)趋于无穷大,但1 / 0 <> Inf 的原因是 1 / 0 是未定义(根据数学定义!) .

【讨论】:

  • "当 n 接近零时,1 / n 的极限将趋于无穷大" 从正方向...如果你从负方向接近 1 / n 接近 负无穷
【解决方案4】:

为什么要拖钓?但我会咬人。这可能会因您构建运算符的方式而异,但定义除法的最传统方式只是乘法的逆函数。也就是说 c = a/b 被定义为 c 是唯一数,使得 c*b = a。

现在考虑 c = 1/0。是否存在唯一的 c 使得 c*0 = 1?当然不在 R 或 C 中。如果我们引入无穷大呢?你可以有一个特殊的情况,说 0*Infinity = 1。但是你破坏了乘法运算符的一堆很好的属性。也就是说,我们想要 2*(0*Infinity) = 2*1 = 2。但我们也想要关联属性。所以 (2*0)*Infinity = 0*Infinity = 1。

一般来说,字段不能扩展为具有 0 的乘法倒数,以保留您想要的属性。

也就是说,我假设您引入经典的 1/0 = Infinity 只是为了吸引用户。下一个问题,为什么语言不承认 0.9 的中继器不等于 1。

【讨论】:

  • 好的,我在这里太粗鲁了。但是 1/0 = Infinity 每次都能吸引我。
  • 郑重声明,这不是拖钓。
【解决方案5】:

0/0-1/0 怎么样?如果你犯了错误怎么办?用Inf 结果向程序发出零除信号并不是一个好主意。

【讨论】:

  • 用一个信号发出信号通常要好得多。就像用信号表明程序已破坏堆栈或堆的最佳方式一样。不是一些在整个过程中传播的虚假价值。我几乎总是启用浮点异常。
【解决方案6】:

在 Java 交互窗格中,我看到了这个。

Welcome to DrJava.  Working directory is /Users/morrison/Desktop/PhotoPuzzle
> int top = 1;
> int bottom = 0;
> top/bottom
java.lang.ArithmeticException: / by zero
> double topFloat = 1;
> double bottomFloat = 0;
> topFloat/bottomFloat
Infinity
> 

浮点数不精确,可能非常接近于零。将整数设为零可能被视为程序员的愚蠢行为。这可能是您看到的两种截然不同的行为。

【讨论】:

    【解决方案7】:

    浮点运算可以检测几种异常情况并以几种不同的方式做出反应:

    • 设置可以稍后测试的状态标志。
    • 立即生成陷阱。

    第一种操作模式允许高性能,而第二种模式允许立即通知可能的错误操作。

    IEEE 754 为引发异常的运算结果定义了一些合理的值(例如:被除数有限非零数和除数为零 → 正确签名的 INFINITY;0/0 → Quiet NaN)。

    带有陷阱的 IEEE 754 意图是存在可以检查操作、操作数(对于无效操作和除以零异常)或结果(对于溢出、下溢和不精确异常)和异常标志的用户模式处理程序并返回一个新的用户定义结果。

    实际上,有些语言甚至不支持访问异常状态标志,更不用说设置陷阱处理程序了。

    即使 C 为陷阱处理程序提供了非常原始的支持,C99 甚至没有定义设置陷阱模式的可移植方式,例如:将一些实现定义的值传递给 fesetenv()。实现通常会引发 SIGFPE,并且用户通常需要访问依赖于 CPU 的状态来实现类似 IEEE-754 的陷阱处理程序。

    【讨论】:

      【解决方案8】:

      因为虽然1 / 0 有时可能近似为INF 或其他类似值,但它并未正式定义为这样。在同一条战线上是10 / 0 < 20 / 0 ?或0 / 0

      【讨论】:

        【解决方案9】:

        部门a | b 本身没有为b = 0 定义。因此,此操作的实现将这种情况映射到一个特殊的值,以表达这个概念。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-04-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多