Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Test if string is a number in Ruby on Rails

I have the following in my application controller:

def is_number?(object)   true if Float(object) rescue false end 

and the following condition in my controller:

if mystring.is_number?  end 

The condition is throwing an undefined method error. I'm guessing I've defined is_number in the wrong place...?

like image 219
Jamie Buchanan Avatar asked Apr 14 '11 09:04

Jamie Buchanan


People also ask

How do you check if a character is a number in Ruby?

You can read more in Ruby's docs for regular expressions. lookAhead =~ /[[:alnum:]]/ if you just want to check whether the char is alphanumeric without needing to know which.

Is number in Ruby?

Ruby supports two types of numbers: Integers: An integer is simply a sequence of digits, e.g., 12, 100. Or in other words, numbers without decimal points are called Integers. In Ruby, Integers are object of class Fixnum(32 or 64 bits) or Bignum(used for bigger numbers).

What is TO_S in Ruby?

The to_s function in Ruby returns a string containing the place-value representation of int with radix base (between 2 and 36). If no base is provided in the parameter then it assumes the base to be 10 and returns.


2 Answers

Create is_number? Method.

Create a helper method:

def is_number? string   true if Float(string) rescue false end 

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   end end 

And then you can call it with:

my_string.is_number? # => true 
like image 195
Jakob S Avatar answered Oct 17 '22 04:10

Jakob S


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.035311s  require '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+$/   end end 

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.016494s  require '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]+$/   end end 
like image 34
Matt Sanders Avatar answered Oct 17 '22 03:10

Matt Sanders