【问题标题】:Division by zero in Haskell在 Haskell 中除以零
【发布时间】:2012-03-10 08:58:09
【问题描述】:

我发现div/ 的行为之间存在相当奇怪的不一致。

*ghci> :t 1 `div` 0
1 `div` 0 :: Integral a => a
*ghci> :t 1 / 0
1 / 0 :: Fractional a => a
*ghci> 1 / 0
Infinity
*ghci> 1 `div` 0
*** Exception: divide by zero

我很惊讶地注意到小数除以零会导致Infinity,而div 正确导致异常。 NaN 对于/ 也可以接受,但为什么是Infinity?这样的结果没有数学上的理由。请问您知道这是什么原因吗?

【问题讨论】:

  • 在数学上,1 / 0 的结果是 Infinity 是完全合理的。它不是唯一合理的返回值,而是最有意义的返回值。请注意,如果您评估 1 / 0 :: Rational,也会收到 divide by zero 错误。
  • @DanielFischer:我不会称其为“数学上完全合理的”,因为这种紧致化(具有正无穷和负无穷大)破坏了很多支持 ℝ 的定理,其中一些在许多程序中都假定。
  • 在处理浮点数时不应该假设这样的事情。即使是像关联性这样的基本属性也不一定成立。 NaNs 的平等也不是自反的! (例如(0/0) /= (0/0).
  • @leftaroundabout 这就是为什么它不是1/0 的唯一合理价值。但是 Alexandrov 紧化也破坏了 ℝ 的许多有用性质——更不用说 Čech 紧化了。
  • @DanielFischer:将其计算为 x->0^+ 的 1/x 的极限是合理的,但不仅仅是经典的简单除法。

标签: math haskell division divide-by-zero


【解决方案1】:

div 不返回Infinity 的原因很简单——Integer 类型中没有无穷大的表示。

/ 返回 Infinity,因为它遵循 IEEE 754 标准(描述浮点数表示),因为默认的 Fractional 类型是 Double。其他具有浮点数的语言(例如 JavaScript)也表现出这种行为。

为了让数学家更加畏缩,如果你除以 0,你会得到不同的结果,尽管 -0 == 0 表示浮点数:

Prelude> 1/(-0)
-Infinity

这也是标准中的行为。

如果您使用不同的小数类型,例如 Rational,您将获得预期的行为:

Prelude> 1 / (0 :: Rational)
*** Exception: Ratio.%: zero denominator

巧合的是,如果您想知道为什么 IntegerDouble 在您的实际操作没有引用它们时是有问题的类型,请查看 Haskell 如何处理 @ 中的默认类型(尤其是数字类型) 987654321@.

简短的版本是,如果您有来自 Num 类的模棱两可的类型,Haskell 将首先尝试 Integer 然后 Double 为该类型。您可以使用default (Type1, Type2...) 语句更改它,或者在模块级别使用default () 语句将其关闭。

【讨论】:

  • 在哪里可以了解default 声明?我以前没见过。
  • 我链接到的报告部分接近尾声。我认为 Haskell 的 Gentle Introduction to Haskell 中也提到了这一点。但是,我不确定它的内容比我在这里介绍的要多得多。 (除非您启用某些扩展,否则它只涉及数字类型并且行为就像我解释的那样。)
  • 我刚刚将它输入到 GHCi 中。你有哪个版本的 GHC?另外,如果你只是尝试1/0,会发生什么?
  • @TikhonJelvis:感谢您的回答,确实很完整。我有最后一个疑问:您提到的 IEEE 标准似乎并不是处理除以零的最佳方法,它有点假设它们是分母的限制,而不是真正的除数。像div 那样抛出异常不是更好吗?
  • @Riccardo Haskell 没有指定用浮点数除以 0 会发生什么。通常,它只会进行浮点除法,所以会发生什么取决于 FPU 所处的模式。这就像 C。
【解决方案2】:

我希望这会有所帮助:

Prelude> 1/0
Infinity
Prelude> -1/0
-Infinity
Prelude> 0/0
NaN

【讨论】:

  • 谢谢...是的,它看起来像一个限制。
【解决方案3】:

出于数学原因,可能不是这样。 Infinity 有时被用作“罪恶箱”:在我们的系统中不能干净地工作的所有东西,把它放在那里。

例子:

Prelude> 10 ** 10 ** 10
Infinity

...在数学上绝对不合理!

【讨论】:

  • 你还没有遇到过硬核有限论者! :)
  • @Ingo Hard core as in zero, one, infinity?
  • @Daniel 我的意思是那些坚持认为像 10^100 这样的数字没有意义的人,因为宇宙中没有那么多物体。但也许他们更喜欢 10^10^10 = NaN
  • @Ingo 你总是可以询问宇宙中物体组合的数量,突然间会有更多的数字对你有用,因为你必须使用阶乘:)
  • @Piotr - 我认为最好以其他理由拒绝他们的论点。虽然(10 ^ 100)!可能确实是巨大的,它仍然是有限的,因此他们觉得自己的愚蠢是有道理的。
【解决方案4】:

小数等于浮点(或双精度)类型。

1/n 的分数,其中 n 变为 0,因此 lim(n→0) 1/n = +∞, lim(n→0) -1/n = -∞,这是有道理的。

【讨论】:

  • 我认为Fractional 约束默认为Double,这是一个浮点类型。阅读我链接到的报告部分。
  • 正确,@TikhonJelvis,除非有默认声明另有说明,否则带有Fractional 约束的模棱两可的类型默认为Double
猜你喜欢
  • 2015-06-25
  • 2016-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-15
相关资源
最近更新 更多