我有这两个 gcd 函数的实现:
def gcd1(a,b)
if a==b
a
elsif a>b
if (a%b)==0
b
else
gcd1(a%b,b)
end
else
if (b%a)==0
a
else
gcd1(a,b%a)
end
end
end
def gcd2(a,b)
if(a==b)
return a
elsif b>a
min,max=a,b
else
min,max=b,a
end
while (max%min)!=0
min,max=max%min,min
end
min
end
函数 gcd1 是尾递归的,而 gcd2 使用 while 循环。
我已经验证了 rubinius 通过对阶乘函数进行基准测试来实现 TCO,只有阶乘函数的基准显示递归版本和迭代版本是“相同的”(我使用了 benchmark-ips)。
但是对于上述情况,基准测试表明 gcd1 至少比 gcd2 快两倍(递归比迭代快两倍,甚至更快)。
我用来基准测试的代码是这样的:
Benchmark.ips do |x|
x.report "gcd1 tail recursive" do
gcd1(12016,18016)
end
x.report "gcd2 while loop" do
gcd2(12016,18016)
end
x.compare!
end
结果 :
Warming up --------------------------------------
gcd1 tail recursive 47.720k i/100ms
gcd2 while loop 23.118k i/100ms
Calculating -------------------------------------
gcd1 tail recursive 874.210k (± 7.1%) i/s - 4.343M
gcd2 while loop 299.676k (± 6.6%) i/s - 1.503M
Comparison:
gcd1 tail recursive: 874209.8 i/s
gcd2 while loop: 299676.2 i/s - 2.92x slower
我正在运行 Arch linux x64,处理器 i5-5200 2.2 GHZ 四核。
红宝石实现是 Rubinius 3.40 。
那么递归怎么能比循环快呢?
更新
只是说斐波那契有相同的情况:尾递归版本至少是循环版本的两倍,我用于斐波那契的程序:http: //pastebin.com/C8ZFB0FR