我读的标准哈斯克尔库的实现(^)的代码:的执行情况(^)
(^) :: (Num a, Integral b) => a -> b -> a
x0^y0 | y0 < 0 = errorWithoutStackTrace "Negative exponent"
| y0 == 0 = 1
| otherwise = f x0 y0
where -- f : x0^y0 = x^y
f x y | even y = f (x * x) (y `quot` 2)
| y == 1 = x
| otherwise = g (x * x) ((y - 1) `quot` 2) x
-- g : x0^y0 = (x^y) * z
g x y z | even y = g (x * x) (y `quot` 2) z
| y == 1 = x * z
| otherwise = g (x * x) ((y - 1) `quot` 2) (x * z)
现在这部分,其中G是定义似乎有些奇怪我为什么不只是实现它像这个:
expo :: (Num a ,Integral b) => a -> b ->a
expo x0 y0
| y0 == 0 = 1
| y0 < 0 = errorWithoutStackTrace "Negative exponent"
| otherwise = f x0 y0
where
f x y | even y = f (x*x) (y `quot` 2)
| y==1 = x
| otherwise = x * f x (y-1)
但的确如此插入3^1000000显示(^)大约比展会快0,04秒。
为什么
(^)
比expo
更快?
这当然不是一个非常戏剧化的问题,但是我认为你的版本效率低下的原因是它将小数字“x”与f的一个大的结果进行了很多倍增。标准版本通过在递归调用之后一直发送剩余因子来生成更平衡的乘法树。 – leftaroundabout
'g'是尾递归,而最后一个'f'不是。我想这里很重要。 – chi