在Haskell中除以零

Ric*_* T. 24 math haskell division divide-by-zero

我发现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
Run Code Online (Sandbox Code Playgroud)

我很惊讶地注意到零除以零导致Infinity,而div正确导致异常.A NaN也可以接受/,但为什么Infinity呢?这样的结果没有数学上的理由.你知道原因吗?

Tik*_*vis 41

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

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

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

Prelude> 1/(-0)
-Infinity
Run Code Online (Sandbox Code Playgroud)

这也是标准的行为.

如果你使用不同的小数类型Rational,你将得到你期望的行为:

Prelude> 1 / (0 :: Rational)
*** Exception: Ratio.%: zero denominator
Run Code Online (Sandbox Code Playgroud)

巧合的是,如果你想知道为什么IntegerDouble在当你的实际操作中没有引用他们问题的类型,看看哈斯克尔如何处理违约类型(特别是数字类型)的报告.

简短的版本是,如果你从Num类中有一个模糊的类型,Haskell将首先尝试Integer然后Double为该类型.您可以使用default (Type1, Type2...)语句更改此设置,也可以使用default ()模块级别的语句将其关闭.

  • @Riccardo Haskell没有指定当用浮点数除以0时应该发生什么.通常,它只会进行浮点除法,所以发生的情况取决于FPU所处的模式.这就像C一样. (3认同)

900*_*000 6

我希望这有帮助:

Prelude> 1/0
Infinity
Prelude> -1/0
-Infinity
Prelude> 0/0
NaN
Run Code Online (Sandbox Code Playgroud)


ami*_*dfv 5

出于数学原因,这可能不是那种方式.Infinity有时被用作"罪孽箱":在我们的系统中干净利落的所有东西,都放在那里.

例:

Prelude> 10 ** 10 ** 10
Infinity
Run Code Online (Sandbox Code Playgroud)

......绝对不是数学上合理的!

  • 你还没有遇到一个硬核有限主义者!:) (2认同)
  • @Ingo你总是可以询问宇宙中对象组合的数量,突然有更多的数字对你有用,因为你必须使用factorial :) (2认同)