如何确定Ruby中Fixnum的长度?

Orc*_*ris 8 ruby integer fixnum ruby-1.9

在我写的脚本中,我想在Ruby中找到Fixnum的长度.我能做到<num>.to_s.length,但有没有办法直接找到Fixnum的长度而不将其转换为String?

ste*_*lag 26

puts Math.log10(1234).to_i + 1 # => 4
Run Code Online (Sandbox Code Playgroud)

您可以将它添加到Fixnum,如下所示:

class Fixnum
  def num_digits
    Math.log10(self).to_i + 1
  end
end

puts 1234.num_digits # => 4
Run Code Online (Sandbox Code Playgroud)

  • 每当我描述一些东西时,我都会感到惊讶.在MRI 1.9.3中,对于由Fixnum表示的任何整数,`n.to_s.length`更快.一个_lot_更快:在我的框中,`n.to_s.length`占据对数方法的三分之一到一半的时间,具体取决于数字的长度.如果数字必须表示为Bignum,则对数方法开始获胜.但是,这两种方法都非常快,大约为0.6毫秒(对数方法),在0.2和0.3毫秒之间(对于字符串方法). (13认同)
  • 小心.这会导致非正数的错误. (4认同)
  • 警告:这也与 0 中断。 (2认同)

San*_*osh 9

Ruby 2.4有一个Integer#digits方法,它返回一个包含数字的数组.

num = 123456
num.digits
# => [6, 5, 4, 3, 2, 1] 
num.digits.count
# => 6 
Run Code Online (Sandbox Code Playgroud)

编辑:

要处理负数(感谢@MatzFan),请使用绝对值.整数#ABS

-123456.abs.digits
# => [6, 5, 4, 3, 2, 1]
Run Code Online (Sandbox Code Playgroud)


dav*_*son 7

Ruby 2.4+ 的旁注

我跑了不同的解决方案的一些基准测试,并且Math.log10(x).to_i + 1实际上是快了很多x.to_s.length@Wayne Conrad评论已过时。在与新的解决方案digits.count是远远落后,尤其是较大的数字:

with_10_digits = 2_040_240_420

print Benchmark.measure { 1_000_000.times { Math.log10(with_10_digits).to_i + 1 } }
# => 0.100000   0.000000   0.100000 (  0.109846)
print Benchmark.measure { 1_000_000.times { with_10_digits.to_s.length } }
# => 0.360000   0.000000   0.360000 (  0.362604)
print Benchmark.measure { 1_000_000.times { with_10_digits.digits.count } }
# => 0.690000   0.020000   0.710000 (  0.717554)

with_42_digits = 750_325_442_042_020_572_057_420_745_037_450_237_570_322

print Benchmark.measure { 1_000_000.times { Math.log10(with_42_digits).to_i + 1 } }
# => 0.140000   0.000000   0.140000 (  0.142757)
print Benchmark.measure { 1_000_000.times { with_42_digits.to_s.length } }
# => 1.180000   0.000000   1.180000 (  1.186603)
print Benchmark.measure { 1_000_000.times { with_42_digits.digits.count } }
# => 8.480000   0.040000   8.520000 (  8.577174)
Run Code Online (Sandbox Code Playgroud)