Topic: how to check if string is a valid number
Hi, I am looking for a isnumeric method for String. Is there something similar avaliable?
"myString".isnumeric
"32.232".isnumeric => true
"Hello".isnumeric => false
Thanks!
You are not logged in. Please login or register.
Rails Forum - Ruby on Rails Help and Discussion Forum » Ruby Programming » how to check if string is a valid number
Hi, I am looking for a isnumeric method for String. Is there something similar avaliable?
"myString".isnumeric
"32.232".isnumeric => true
"Hello".isnumeric => false
Thanks!
regular expressions will do.
/^[\d]+(\.[\d]+){0,1}$/ === "23.362" => true
/^[\d]+(\.[\d]+){0,1}$/ === "23.36.2" => false
/^[\d]+(\.[\d]+){0,1}$/ === "2362" => true
/^[\d]+(\.[\d]+){0,1}$/ === "-23.362" => true
/\A-?\d+\Z/ === "-23.362" => false
Duplex, using .to_f.to_s, "0" would be returned as not-a-number
jbartel,
I mean the other way round in my previous post. Does anybody see a problem using /\A-?\d+\Z/
/^[\d]+(\.[\d]+){0,1}$/ === "-23.362" => false
/\A-?\d+\Z/ === "-23.362" => true
Duplex, using .to_f.to_s, "0" would be returned as not-a-number
Your reply is confusing now as i removed my post after seeing better replies ![]()
anyway, your're wrong as i did a comparison which would simply return true/false:
#if self is a string:
self.to_i.to_s == self
#should return true as "1".to_i.to_s is "1"
#(for integers of course, floats are a different thing)
Duplex, to_i.to_s would work for integers only. I am looking to check floats as well. e.g. "-32.232". Reg exp is indeed a better solution.
Here's a revised version that works for floats too.
#!/usr/bin/ruby -wdef is_a_number?(s)
s.to_s.match(/\A[+-]?\d+?(\.\d+)?\Z/) == nil ? false : true
end
puts is_a_number?(5)
puts is_a_number?("+256.375")
puts is_a_number?("-37.3")
puts is_a_number?("x")
puts is_a_number?(-37.3)
puts is_a_number?("2.3.3")
Thanks Specious,worked well!
Good call on the negative numbers! Glad someone caught that!
On a related note the to_f and to_i methods are almost too good. If it can't parse something it returns either 0 or the components of it that it could figure out. That leads to ambiguous results since "ASDFasdfasfd".to_i returns 0 instead of nil or raising an exception.
The Float() method is nice for this problem, and it catches edge cases that custom regular expressions can easily miss.
def numeric?(object)
true if Float(object) rescue false
end
Nice and simple. And the rescue clause makes it bulletproof. I like it!
Yep, did some brief testing and I like Chap's suggestion the best. Thanks!
Thanks, this was a very helpful thread - I thought I'd share my quicky bench test of the two methods because the performance results that I got was not what I expected:
arry = %w[a 1a a2 1.0b 1.1.0 0 1 1.1 0.1 -1 ]
def is_numeric?(i)
i.to_i.to_s == i || i.to_f.to_s == i
end
def is_number?(i)
true if Float(i) rescue false
end
a = Time.now
100000.times { arry.each { |n| is_numeric?(n) } }
puts Time.now - a
a = Time.now
100000.times { arry.each { |n| is_number?(n) } }
puts Time.now - aI get:
6.1308
13.1352
So explicitly creating a Float is twice as slow as converting to an integer or float and back to a string.
I also ran this with all values that would return false and got more of a 3 times slowdown, so I wonder if it has more to do with exception handling than object creation?
I've added is_a_number? code mentioned above to the test:
def is_a_number?(s)
s.to_s.match(/\A[+-]?\d+?(\.\d+)?\Z/) == nil ? false : true
end
a = Time.now
100000.times { arry.each { |n| is_a_number?(n) } }
puts Time.now - aThe result is:
1.925948 is_numeric?
3.642966 is_number?
1.608794 is_a_number?
(yep, my machine is slightly faster
)
The latter sub is the fastest one. You can win 10% more by removing to_s, but this is dangerous.
I know this thread is kind of old now, but I'd like to point out that the regular expression method of detection shown above does not correspond completely with the Float() method. Specifically, calling:
is_a_number?(".0")yields false in irb (1.8.7) while Float(".0") yields 0.0 (or true using ChrisJ's is_number? method above)
For some situations, catching ".0" as valid may be important.
Likewise using either the num.to_i.to_s or num.to_f.to_s is problematic if the input may be a numeric string in a non-normalized form: "09".to_i.to_s != "9" and "5e-1".to_f.to_s != "0.5"
For these reasons I prefer the apparently slower Float() method (minzastro's is_a_number? method) better when you want to catch these valid though possibly non-normalized numeric strings.
Yes i wanted to know this answer, this thread is very helpful and it throws more insight to what iam looking for.
I know this is old, but wanna see something cool?
begin Float("Test") ; true end rescue falsereturns false
Or as a one-liner extension to Number:
class String
def is_numeric?
begin Float(self) ; true end rescue false
end
endOr, more readable:
class String
def is_numeric?
Float(self)
true
rescue
false
end
endWorks for floats, and specifically why I was interested - works for "0" just fine. (string.to_f does not, as "0".to_f == 0 and "Anything".to_f == 0)
Float not working perfect :
because float number 545e5 is correct
true if Float("545e5") rescue false
=> true
Last edited by pauliuspr (2012-10-19 07:32:29)
string.is_a? Integer
Hosting provided by aTech Media