Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Without Converting to a String, How Many Digits Does a Fixnum Have?

I want find the length of a Fixnum, num, without converting it into a String.

In other words, how many digits are in num without calling the .to_s() method:

num.to_s.length
like image 481
Orcris Avatar asked Dec 22 '12 18:12

Orcris


3 Answers

Ruby 2.4 has an Integer#digits method, which return an Array containing the digits.

num = 123456
num.digits
# => [6, 5, 4, 3, 2, 1] 
num.digits.count
# => 6 

EDIT:

To handle negative numbers (thanks @MatzFan), use the absolute value. Integer#abs

-123456.abs.digits
# => [6, 5, 4, 3, 2, 1]
like image 86
Santhosh Avatar answered Nov 15 '22 19:11

Santhosh


Sidenote for Ruby 2.4+

I ran some benchmarks on the different solutions, and Math.log10(x).to_i + 1 is actually a lot faster than x.to_s.length. The comment from @Wayne Conrad is out of date. The new solution with digits.count is trailing far behind, especially with larger numbers:

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)
like image 37
davegson Avatar answered Nov 15 '22 19:11

davegson


puts Math.log10(1234).to_i + 1 # => 4

You could add it to Fixnum like this:

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

puts 1234.num_digits # => 4
like image 37
steenslag Avatar answered Nov 15 '22 21:11

steenslag