check numbers

Hello people,

how to check string to know if it is number or not.

ex: isnumber('text') ==> false isnumber('22') ==> true

Thanks.

There are a few ways to do this. I'll give some examples for checking if the string is an integer, which might be sufficient for you. Checking for floats, rationals, etc will be more complex.

# is_integer.rb class String   def is_integer?     !self.empty? && self =~ /\A\d+\Z/ # not the empty string and containing only one or more digits   end

  def is_integer2?     !self.empty? && Integer(self) rescue false # not the empty string and capable of being coerced by Integer()   end

  def is_integer3?     !self.empty? && self.scan(/\D/).empty? # not the empty string and containing no non-digit characters   end end

Here is one benchmark:

["", "1", "123", "foo", "foo123"].each { |string| string.is_integer?} # (n = 10,000)                 user system total real     regex: 0.070000 0.000000 0.070000 ( 0.065365) Integer(): 0.580000 0.040000 0.620000 ( 0.620194)      scan: 0.150000 0.000000 0.150000 ( 0.150243)

Using Integer and rescuing the thrown exception is quick for integer strings but grossly inefficient for non-integer strings (as expected). The regex is fastest all-around of the three examples given and benchmarking shows that short-circuiting on the empty string really speeds up the special case of "".is_integer?

Feel free to suggest other implementations. I'll put the lib, unit test and benchmark files on my blog for you to use. (As soon as I get my blog up and running. Probably tomorrow. Stay tuned.) Until then, here's the benchmark used above:

# is_integer_bm.rb require 'benchmark' require 'is_integer' # your is_integer.rb where the extension to String is located

STRINGS = ["", "1", "123", "foo", "foo123"]

def bench_total   n = 10000   puts "\n"   print STRINGS.inspect   print".each { |string| string.is_integer?}"   print " # (n = 10,000)\n"   Benchmark.bm(10) do |x|     x.report(" regex:") { n.times { STRINGS.each{ |str| str.is_integer? } } }     x.report("Integer():") { n.times { STRINGS.each{ |str| str.is_integer2? } } }     x.report(" scan:") { n.times { STRINGS.each{ |str| str.is_integer3? } } }   end end

bench_total

Rein

def isnumber(string)    string.to_i.to_s == string ? true : false end

-faisal

faisal,

The ternary here is useless as == already returns a boolean, and this is also integer only rather than any number, so changing your method to:

class String   def is_integer?     self.to_i.to_s == self   end end

and adding it to the benchmark, we get:

["", "1", "123", "foo", "foo123"].each { |string| string.is_integer?} # (n = 10,000)                 user system total real     regex: 0.070000 0.000000 0.070000 ( 0.069953) Integer(): 0.580000 0.040000 0.620000 ( 0.635358)      scan: 0.150000 0.000000 0.150000 ( 0.172896) to_i.to_s: 0.150000 0.000000 0.150000 ( 0.157933)

Or roughly equal to the scan method but still about half as fast as the regex. So far you're in second place. Thanks for playing :wink:

Incidentally faisal's method does actually work as a test for integer- ness. (There has to be a better word...) My only issue with it is that it is not very intention revealing. Then again, neither is the regex if you aren't familiar with regexen.

Incidentally, the regex method without the check for empty? is actually slightly faster overall than with the check for empty? so the most performant method so far is:

class String   def is_integer?     self =~ /\A\d+\Z/   end end

rewritten in a object oriented manner:

class String   def is_integer?     self.to_i >= 1   end end

"0".is_integer? #=> false "-123".is_integer? #=> false

'fraid not.

You did, however, remind me about negative integers.

class String   def is_integer?     self =~ /\A-?\d+\Z/   end end

and the scan method won't work on negative integers. Whoops!

For posterity: http://reinh.com/2007/9/4/string-is_integer

Rein

i could argue that it's mostly for readability, although having used a ternary in the first place i could argue that i should have an entire chorus lined up to laugh at the code.

-faisal