为什么在Haskell 0 ^ 0 == 1?为什么不0 ^ 0 == 0?或者也许应该引起一些错误...
*Main> 0^0
1
*Main> 0**0
1.0
先谢谢
GHCi,版本7.10.3
答案 0 :(得分:9)
当你查看签名时,这有点意义。
(^) :: (Num a, Integral b) => a -> b -> a
这个设计用于非负整数指数。它可能是递归实现的,所以它的行为就像重复乘法一样。因此,对于零功率而言,任何事物都是一个"是先例的规则,因为我们真的在谈论重复乘法。
(^^) :: (Fractional a, Integral b) => a -> b -> a
这个很像前一个,除了它也适用于负指数,因为它的基数是小数。尽管如此,它的行为类似于重复乘法或重复除法(如果指数分别为正或负),所以再次重复这些操作中的任何一个零时都应该导致乘法身份1
。< / p>
(**) :: Floating a => a -> a -> a
在Haskell中,浮点类型通常符合IEEE标准,IEEE特别将pow(0.0, 0.0)
定义为1.0
。因此,我想,Haskell只是符合标准,因此在这种情况下它与其他语言的行为一致。
答案 1 :(得分:2)
Haskell就是这样做的,因为数学以这种方式定义它。数学就是这样做的,因为0⁰= 1·0⁰,即1乘以其他零次,即1 不乘以任何。数学家认为遵守规则是更有意义的,即第零次幂的任何东西都是1(无效产品),而不是任何幂为零的规则。
当你尝试用乘法和除法来定义指数时,这很有意义。例如,如果您尝试在Haskell中定义^
,则可能会出现:
(^) a b = product $ replicate b a
这相当于:
(^) a b = foldr (*) 1 (replicate b a)
包含零数字的列表为空。空列表的乘积为1,否则很多事情都会中断,例如product (xs++[])
不等于(product xs) * (product [])
。
或者如果您编写了最简单的递归解决方案:
(^) _ 0 = 1
(^) a b = a*(a^(b-1))
除了基本和递归情况之外,您还需要一个特殊情况,将0⁰定义为除1以外的对数。
正如@leftroundabout指出的那样,我的答案假设我们正在使用离散数学。计算机科学家几乎都是,而Haskell是由学术计算机科学家设计的。
如果我们在计算机上使用连续函数,我们必须进行数值近似。在这种情况下,最有效的实现将是使用我们正在运行的机器的FPU的实现。 2017年,这将遵循IEEE标准,即标准为pow(0.0,0.0)= 1.0。
编写和证明关于符合约定的指数函数的语句只是稍微简单一些。
答案 2 :(得分:0)
这只是一个数学定律。任何提升到0幂的正数都等于1.应该没有错误
答案 3 :(得分:0)
Haskell是函数式编程语言。功能语言在其基础上使用λ-calculus 。在λ演算中使用Church编码对数字文字进行编码。因此,如果您使用Church对0^0
进行编码,然后使用β减少对λ项进行标准化,则会得到1
,如下所示:
0^0 = (λn.λm.λs.λz.m n s z) (λs.λz.z) (λs.λz.z) = λs.λz.s z = 1
我认为这可以解释为什么Haskell决定遵循选择的模型。