Cas*_*how 3 ruby string performance integer
假设我想取一个数字并将其数字作为数组返回Ruby.
对于这个特定的目的或者对于字符串函数和数字函数一般来说哪个更快?
这些是我认为最常用的算法:
使用字符串: n.to_s.split(//).map {|x| x.to_i}
使用数字:
array = []
until n = 0
m = n % 10
array.unshift(m)
n /= 10
end
Run Code Online (Sandbox Code Playgroud)
差异似乎小于一个数量级,对于Fixnums,基于整数的方法更快.对于Bignums,相对性能开始或多或少均匀,随着数字位数的增长,字符串方法显着胜出.
#!/usr/bin/env ruby
require 'profile'
$n = 1234567890
10000.times do
$n.to_s.split(//).map {|x| x.to_i}
end
Run Code Online (Sandbox Code Playgroud)
% 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
Run Code Online (Sandbox Code Playgroud)
#!/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
Run Code Online (Sandbox Code Playgroud)
% 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
Run Code Online (Sandbox Code Playgroud)
该模式似乎也适用于较小的数字.对于$n = 12345基于字符串的方法,大约800ms,对于基于整数的方法,大约为550ms.
当我越过边界进入Bignums时,比如说,$n = 12345678901234567890两种方法都得到了2375ms.看起来差别很大,我可能会认为内部本地供电Bignum是字符串式的.但是,文档似乎另有说法.
出于学术目的,我再次将位数加倍$n = 1234567890123456789012345678901234567890.我得到了大约4450ms的字符串方法和9850ms的整数方法,一个明显的逆转,排除了我以前的假设.
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
Run Code Online (Sandbox Code Playgroud)

史蒂文的回应令人印象深刻,但我看了几分钟并且无法将其提炼成一个简单的答案,所以这是我的.
使用我在下面提供的数字方法是最快的.它使用起来也非常快(而且更容易)num.to_s.each_char.map(&:to_i).
它使用起来最快num.to_s.each_char.map(&:to_i).
如果速度老实说是你使用什么代码的决定因素(意思是不是邪恶的),那么这个代码是这项工作的最佳选择.
class Integer
def digits
working_int, digits = self, Array.new
until working_int.zero?
digits.unshift working_int % 10
working_int /= 10
end
digits
end
end
class Bignum
def digits
to_s.each_char.map(&:to_i)
end
end
Run Code Online (Sandbox Code Playgroud)
以下是我考虑得出这个结论的方法.