差异似乎小于一个数量级,对于Fixnums,基于整数的方法更快。对于Bignums,相对性能开始时或多或少是平的,随着位数的增加,字符串方法明显胜出。
作为字符串
程序
#!/usr/bin/env ruby
require 'profile'
$n = 1234567890
10000.times do
$n.to_s.split(//).map {|x| x.to_i}
end
输出
% cumulative self self total
time seconds seconds calls ms/call ms/call name
55.64 0.74 0.74 10000 0.07 0.10 Array#map
21.05 1.02 0.28 100000 0.00 0.00 String#to_i
10.53 1.16 0.14 1 140.00 1330.00 Integer#times
7.52 1.26 0.10 10000 0.01 0.01 String#split
5.26 1.33 0.07 10000 0.01 0.01 Fixnum#to_s
0.00 1.33 0.00 1 0.00 1330.00 #toplevel
作为整数
程序
#!/usr/bin/env ruby
require 'profile'
$n = 1234567890
10000.times do
array = []
n = $n
until n == 0
m = n%10
array.unshift(m)
n /= 10
end
array
end
输出
% cumulative self self total
time seconds seconds calls ms/call ms/call name
70.64 0.77 0.77 1 770.00 1090.00 Integer#times
29.36 1.09 0.32 100000 0.00 0.00 Array#unshift
0.00 1.09 0.00 1 0.00 1090.00 #toplevel
附录
这种模式似乎也适用于较小的数字。对于$n = 12345,基于字符串的方法大约需要 800 毫秒,而基于整数的方法大约需要 550 毫秒。
当我越过边界进入Bignums 时,例如,使用$n = 12345678901234567890,两种方法的时间均为 2375 毫秒。看起来差异很好地平衡了,我认为这意味着内部本地供电Bignum 是类似字符串的。但是,documentation 似乎另有说明。
出于学术目的,我再次将位数加倍为$n = 1234567890123456789012345678901234567890。我得到了大约 4450 毫秒的字符串方法和 9850 毫秒的整数方法,这是一个完全相反的结果,排除了我之前的假设。
总结
Number of digits | String program | Integer program | Difference
---------------------------------------------------------------------------
5 | 800ms | 550ms | Integer wins by 250ms
10 | 1330ms | 1090ms | Integer wins by 240ms
20 | 2375ms | 2375ms | Tie
40 | 4450ms | 9850ms | String wins by 4400ms