包含数字的字符串与数字相比要慢多少?

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)

Ste*_*ven 8

差异似乎小于一个数量级,对于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)


Jos*_*eek 7

史蒂文的回应令人印象深刻,但我看了几分钟并且无法将其提炼成一个简单的答案,所以这是我的.

对于Fixnums

使用我在下面提供的数字方法是最快的.它使用起来也非常快(而且更容易)num.to_s.each_char.map(&:to_i).


对于Bignums

它使用起来最快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)

以下是我考虑得出这个结论的方法.