Test if string is a number in Ruby on Rails Test if string is a number in Ruby on Rails ruby ruby

Test if string is a number in Ruby on Rails


Create is_number? Method.

Create a helper method:

def is_number? string  true if Float(string) rescue falseend

And then call it like this:

my_string = '12.34'is_number?( my_string )# => true

Extend String Class.

If you want to be able to call is_number? directly on the string instead of passing it as a param to your helper function, then you need to define is_number? as an extension of the String class, like so:

class String  def is_number?    true if Float(self) rescue false  endend

And then you can call it with:

my_string.is_number?# => true


Here's a benchmark for common ways to address this problem. Note which one you should use probably depends on the ratio of false cases expected.

  1. If they are relatively uncommon casting is definitely fastest.
  2. If false cases are common and you are just checking for ints, comparison vs a transformed state is a good option.
  3. If false cases are common and you are checking floats, regexp is probably the way to go

If performance doesn't matter use what you like. :-)

Integer checking details:

# 1.9.3-p448## Calculating -------------------------------------#                 cast     57485 i/100ms#            cast fail      5549 i/100ms#                 to_s     47509 i/100ms#            to_s fail     50573 i/100ms#               regexp     45187 i/100ms#          regexp fail     42566 i/100ms# -------------------------------------------------#                 cast  2353703.4 (±4.9%) i/s -   11726940 in   4.998270s#            cast fail    65590.2 (±4.6%) i/s -     327391 in   5.003511s#                 to_s  1420892.0 (±6.8%) i/s -    7078841 in   5.011462s#            to_s fail  1717948.8 (±6.0%) i/s -    8546837 in   4.998672s#               regexp  1525729.9 (±7.0%) i/s -    7591416 in   5.007105s#          regexp fail  1154461.1 (±5.5%) i/s -    5788976 in   5.035311srequire 'benchmark/ips'int = '220000'bad_int = '22.to.2'Benchmark.ips do |x|  x.report('cast') do    Integer(int) rescue false  end  x.report('cast fail') do    Integer(bad_int) rescue false  end  x.report('to_s') do    int.to_i.to_s == int  end  x.report('to_s fail') do    bad_int.to_i.to_s == bad_int  end  x.report('regexp') do    int =~ /^\d+$/  end  x.report('regexp fail') do    bad_int =~ /^\d+$/  endend

Float checking details:

# 1.9.3-p448## Calculating -------------------------------------#                 cast     47430 i/100ms#            cast fail      5023 i/100ms#                 to_s     27435 i/100ms#            to_s fail     29609 i/100ms#               regexp     37620 i/100ms#          regexp fail     32557 i/100ms# -------------------------------------------------#                 cast  2283762.5 (±6.8%) i/s -   11383200 in   5.012934s#            cast fail    63108.8 (±6.7%) i/s -     316449 in   5.038518s#                 to_s   593069.3 (±8.8%) i/s -    2962980 in   5.042459s#            to_s fail   857217.1 (±10.0%) i/s -    4263696 in   5.033024s#               regexp  1383194.8 (±6.7%) i/s -    6884460 in   5.008275s#          regexp fail   723390.2 (±5.8%) i/s -    3613827 in   5.016494srequire 'benchmark/ips'float = '12.2312'bad_float = '22.to.2'Benchmark.ips do |x|  x.report('cast') do    Float(float) rescue false  end  x.report('cast fail') do    Float(bad_float) rescue false  end  x.report('to_s') do    float.to_f.to_s == float  end  x.report('to_s fail') do    bad_float.to_f.to_s == bad_float  end  x.report('regexp') do    float =~ /^[-+]?[0-9]*\.?[0-9]+$/  end  x.report('regexp fail') do    bad_float =~ /^[-+]?[0-9]*\.?[0-9]+$/  endend


class String  def numeric?    return true if self =~ /\A\d+\Z/    true if Float(self) rescue false  endend  p "1".numeric?  # => truep "1.2".numeric? # => truep "5.4e-29".numeric? # => truep "12e20".numeric? # truep "1a".numeric? # => falsep "1.2.3.4".numeric? # => false