How to determine the length of Fixnum in Ruby?

In the script I'm writing, I want to find the length of Fixnum in Ruby. I could do <num>.to_s.length , but is there a way to directly find the length of Fixnum without converting it to a string?

+8
source share
7 answers
 puts Math.log10(1234).to_i + 1 # => 4 

You can add it to Fixnum as follows:

 class Fixnum def num_digits Math.log10(self).to_i + 1 end end puts 1234.num_digits # => 4 
+25
source

Ruby 2.4 has Integer # digitits , which returns an array containing numbers.

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

EDIT:

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

 -123456.abs.digits # => [6, 5, 4, 3, 2, 1] 
+9
source

Although the top voted loop is good, it is not very Ruby and will be slow for large numbers, .to_s is a built-in function and therefore will be much faster. ALMOST universal built-in functions will be much faster than built loops or iterators.

+4
source

Sidenote for Ruby 2.4+

I did some tests for different solutions, and Math.log10(x).to_i + 1 is actually much faster than x.to_s.length . Comment by @Wayne Conrad is deprecated. The new solution with digits.count is far behind, especially with large 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) 
+4
source

Another way:

 def ndigits(n) n=n.abs (1..1.0/0).each { |i| return i if (n /= 10).zero? } end ndigits(1234) # => 4 ndigits(0) # => 1 ndigits(-123) # => 3 
+1
source

If you do not want to use a regular expression, you can use this method:

 def self.is_number(string_to_test) is_number = false # use to_f to handle float value and to_i for int string_to_compare = string_to_test.to_i.to_s string_to_compare_handle_end = string_to_test.to_i # string has to be the same if(string_to_compare == string_to_test) is_number = true end # length for fixnum in ruby size = Math.log10(string_to_compare_handle_end).to_i + 1 # size has to be the same if(size != string_to_test.length) is_number = false end is_number end 
0
source

You do not need to fantasize, you can do it so simply.

 def l(input) output = 1 while input - (10**output) > 0 output += 1 end return output end puts l(456) 
0
source

All Articles