我正在使用递归调用来计算指数。它工作到2 ** 63,然后归零。我认为我有些溢出。但是我以为Haskell处理了这个问题。
我尝试使用数字直到64,然后检查到Int。
power :: Int -> Int
power n = if n==0 then 1 else 2*power(n-1)
main = return()
在GHCI中
1152921504606846976
*Main> power 70
0
*Main> power 65
0
*Main> power 64
0
*Main> power 63
-9223372036854775808
*Main> power 62
4611686018427387904
答案 0 :(得分:6)
我认为我有些溢出。但是我以为Haskell处理了这个问题。
确实是溢出的,Haskell具有一种可以处理任意大小的整数的类型:Integer
。但是,您使用Int
。如文档所指定,对于Int
:
data Int
一种固定精度整数类型,其范围至少为
[-2^29 .. 2^29-1]
。可以通过使用minBound
类中的maxBound
和Bounded
来确定给定实现的确切范围。
Int
因此具有固定的字长,并且可能会溢出。您可以使用Integer
,但是它可以代表任意数字(直到内存用完为止)。
如果因此将定义更改为:
power :: Integer -> Integer
power 0 = 1
power n = 2 * power (n-1)
我们确实可以计算 2 128 :
Prelude> power 128
340282366920938463463374607431768211456
请注意,我们可以通过以下方法提高此power
函数的性能:
power :: Integral i => i -> Integer
power 0 = 1
power n | even n = p * b2
| otherwise = 2 * b2 * b2
where b2 = power (div n 2)
这成立,因为 b 2 a =(b 2)a 。因此,如果我们假设所有操作都在恒定时间内进行,则此算法在 O(log p)中运行。但是,这并不完全成立,因为b2
可能会很大,因此乘以b2
不会在恒定时间内运行。