Test if string is a number in Ruby on Rails
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
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...?
ruby-on-rails ruby string integer
add a comment |
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...?
ruby-on-rails ruby string integer
4
I know a lot of people are here because of codeschool's Rails for Zombies Testing class. Just wait for him to keep explaining. The tests aren't supposed to pass --- its OK to have you test fail in error, you can always patch rails to invent methods such as self.is_number?
– boulder_ruby
Feb 28 '13 at 19:33
The accepted answer fails on cases like "1,000" and is a 39x slower than using a regex approach. See my answer below.
– pthamm
Feb 19 '16 at 23:10
add a comment |
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...?
ruby-on-rails ruby string integer
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...?
ruby-on-rails ruby string integer
ruby-on-rails ruby string integer
edited Jun 3 '14 at 2:58
user664833
11k1771114
11k1771114
asked Apr 14 '11 at 9:56
Jamie BuchananJamie Buchanan
2,24821622
2,24821622
4
I know a lot of people are here because of codeschool's Rails for Zombies Testing class. Just wait for him to keep explaining. The tests aren't supposed to pass --- its OK to have you test fail in error, you can always patch rails to invent methods such as self.is_number?
– boulder_ruby
Feb 28 '13 at 19:33
The accepted answer fails on cases like "1,000" and is a 39x slower than using a regex approach. See my answer below.
– pthamm
Feb 19 '16 at 23:10
add a comment |
4
I know a lot of people are here because of codeschool's Rails for Zombies Testing class. Just wait for him to keep explaining. The tests aren't supposed to pass --- its OK to have you test fail in error, you can always patch rails to invent methods such as self.is_number?
– boulder_ruby
Feb 28 '13 at 19:33
The accepted answer fails on cases like "1,000" and is a 39x slower than using a regex approach. See my answer below.
– pthamm
Feb 19 '16 at 23:10
4
4
I know a lot of people are here because of codeschool's Rails for Zombies Testing class. Just wait for him to keep explaining. The tests aren't supposed to pass --- its OK to have you test fail in error, you can always patch rails to invent methods such as self.is_number?
– boulder_ruby
Feb 28 '13 at 19:33
I know a lot of people are here because of codeschool's Rails for Zombies Testing class. Just wait for him to keep explaining. The tests aren't supposed to pass --- its OK to have you test fail in error, you can always patch rails to invent methods such as self.is_number?
– boulder_ruby
Feb 28 '13 at 19:33
The accepted answer fails on cases like "1,000" and is a 39x slower than using a regex approach. See my answer below.
– pthamm
Feb 19 '16 at 23:10
The accepted answer fails on cases like "1,000" and is a 39x slower than using a regex approach. See my answer below.
– pthamm
Feb 19 '16 at 23:10
add a comment |
12 Answers
12
active
oldest
votes
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
2
This is a bad idea. "330.346.11".to_f # => 330.346
– epochwolf
Nov 2 '11 at 23:15
11
There is noto_f
in the above, and Float() doesn't exhibit that behavior:Float("330.346.11")
raisesArgumentError: invalid value for Float(): "330.346.11"
– Jakob S
Nov 3 '11 at 10:29
6
If you use that patch, I'd rename it to numeric?, to stay in line with ruby naming conventions (Numeric classes inherit from Numeric, is_ prefixes are javaish).
– Konrad Reiche
Jun 24 '12 at 18:34
9
Not really relevant to the original question, but I'd probably put the code inlib/core_ext/string.rb
.
– Jakob S
Aug 7 '12 at 8:48
1
I don't think theis_number?(string)
bit works Ruby 1.9. Maybe that is part of Rails or 1.8?String.is_a?(Numeric)
works. See also stackoverflow.com/questions/2095493/….
– Ross Attrill
Jun 16 '14 at 7:10
|
show 7 more comments
class String
def numeric?
return true if self =~ /Ad+Z/
true if Float(self) rescue false
end
end
p "1".numeric? # => true
p "1.2".numeric? # => true
p "5.4e-29".numeric? # => true
p "12e20".numeric? # true
p "1a".numeric? # => false
p "1.2.3.4".numeric? # => false
11
/^d+$/
is not a safe regexp in Ruby,/Ad+Z/
is. (e.g. "42nsome text" would returntrue
)
– Timothee A
Sep 1 '14 at 15:18
To clarify on @TimotheeA's comment, it is safe to use/^d+$/
if dealing with lines but in this case it's about beginning and end of a string, thus/Ad+Z/
.
– Julio
Oct 9 '14 at 20:09
1
Shouldn't answers be edited to change the actual answer BY the responder? changing the answer in an edit if you're not the responder seems...possibly underhanded and should be out of bounds.
– jaydel
Jul 20 '16 at 15:43
Where should I put these codes?
– zx1986
Jul 7 '17 at 4:10
2
Z allows to have n at the end of the string, so "123n" will pass validation, regardless that it's not fully numeric. But if you use z then it will be more correct regexp: /Ad+z/
– SunnyMagadan
Aug 14 '17 at 9:14
add a comment |
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.
- If they are relatively uncommon casting is definitely fastest.
- If false cases are common and you are just checking for ints, comparison vs a transformed state is a good option.
- 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
add a comment |
Relying on the raised exception is not the fastest, readable nor reliable solution.
I'd do the following :
my_string.should =~ /^[0-9]+$/
1
This only works for positive integers, however. Values like '-1', '0.0', or '1_000' all return false even though they are valid numeric values. You're looking at something like /^[-.0-9]+$/, but that erroneously accepts '--'.
– Jakob S
Apr 14 '11 at 11:03
10
From Rails 'validates_numericality_of': raw_value.to_s =~ /A[+-]?d+Z/
– Morten
Aug 17 '12 at 20:09
NoMethodError: undefined method `should' for "asd":String
– sergserg
Oct 9 '14 at 22:08
In the latest rspec, this becomesexpect(my_string).to match(/^[0-9]+$/)
– Damien MATHIEU
Oct 10 '14 at 8:55
I like:my_string =~ /A-?(d+)?.?d+Z/
it lets you do '.1', '-0.1', or '12' but not '' or '-' or '.'
– Josh
Sep 2 '16 at 0:05
|
show 1 more comment
no you're just using it wrong. your is_number? has an argument. you called it without the argument
you should be doing is_number?(mystring)
Based on the is_number? method in the question, using is_a? is not giving the correct answer. Ifmystring
is indeed a String,mystring.is_a?(Integer)
will always be false. It looks like he wants a result likeis_number?("12.4") #=> true
– Jakob S
Apr 14 '11 at 10:15
mmm good point, lemme update that
– corroded
Apr 14 '11 at 10:20
Jakob S is correct. mystring is indeed always a string, but may be comprise of just numbers. perhaps my question should have been is_numeric? so as not to confuse the datatype
– Jamie Buchanan
Apr 14 '11 at 10:23
add a comment |
Tl;dr: Use a regex approach. It is 39x faster than the rescue approach in the accepted answer and also handles cases like "1,000"
def regex_is_number? string
no_commas = string.gsub(',', '')
matches = no_commas.match(/-?d+(?:.d+)?/)
if !matches.nil? && matches.size == 1 && matches[0] == no_commas
true
else
false
end
end
--
The accepted answer by @Jakob S works for the most part, but catching exceptions can be really slow. In addition, the rescue approach fails on a string like "1,000".
Let's define the methods:
def rescue_is_number? string
true if Float(string) rescue false
end
def regex_is_number? string
no_commas = string.gsub(',', '')
matches = no_commas.match(/-?d+(?:.d+)?/)
if !matches.nil? && matches.size == 1 && matches[0] == no_commas
true
else
false
end
end
And now some test cases:
test_cases = {
true => ["5.5", "23", "-123", "1,234,123"],
false => ["hello", "99designs", "(123)456-7890"]
}
And a little code to run the test cases:
test_cases.each do |expected_answer, cases|
cases.each do |test_case|
if rescue_is_number?(test_case) != expected_answer
puts "**rescue_is_number? got #{test_case} wrong**"
else
puts "rescue_is_number? got #{test_case} right"
end
if regex_is_number?(test_case) != expected_answer
puts "**regex_is_number? got #{test_case} wrong**"
else
puts "regex_is_number? got #{test_case} right"
end
end
end
Here is the output of the test cases:
rescue_is_number? got 5.5 right
regex_is_number? got 5.5 right
rescue_is_number? got 23 right
regex_is_number? got 23 right
rescue_is_number? got -123 right
regex_is_number? got -123 right
**rescue_is_number? got 1,234,123 wrong**
regex_is_number? got 1,234,123 right
rescue_is_number? got hello right
regex_is_number? got hello right
rescue_is_number? got 99designs right
regex_is_number? got 99designs right
rescue_is_number? got (123)456-7890 right
regex_is_number? got (123)456-7890 right
Time to do some performance benchmarks:
Benchmark.ips do |x|
x.report("rescue") { test_cases.values.flatten.each { |c| rescue_is_number? c } }
x.report("regex") { test_cases.values.flatten.each { |c| regex_is_number? c } }
x.compare!
end
And the results:
Calculating -------------------------------------
rescue 128.000 i/100ms
regex 4.649k i/100ms
-------------------------------------------------
rescue 1.348k (±16.8%) i/s - 6.656k
regex 52.113k (± 7.8%) i/s - 260.344k
Comparison:
regex: 52113.3 i/s
rescue: 1347.5 i/s - 38.67x slower
Thanks for the benchmark. The accepted answer has the advantage of accepting inputs like5.4e-29
. I guess your regex could be tweaked to accept those also.
– Jodi
Feb 24 '16 at 16:27
1
Handling cases like 1,000 is really hard, since it depends on user intention. There are many, many ways for humans to format numbers. Is 1,000 about equal to 1000, or about equal to 1? Most of the world says it's about 1, not a way to show the integer 1000.
– James Moore
Feb 25 '17 at 18:59
add a comment |
this is how i do it, but i think too there must be a better way
object.to_i.to_s == object || object.to_f.to_s == object
4
It does not recognize floating notation, e.g. 1.2e+35.
– hipertracker
Jul 25 '12 at 16:13
add a comment |
In rails 4, you need to put
require File.expand_path('../../lib', __FILE__) + '/ext/string'
in your config/application.rb
1
actually you don't need to do this, you could just put string.rb in "initializers" and it works!
– mahatmanich
Jun 16 '14 at 8:32
That's it! so cool!
– zx1986
Jul 7 '17 at 6:14
add a comment |
If you prefer not to use exceptions as part of the logic, you might try this:
class String
def numeric?
!!(self =~ /^-?d+(.d*)?$/)
end
end
Or, if you want it to work across all object classes, replace class String
with class Object
an convert self to a string: !!(self.to_s =~ /^-?d+(.d*)?$/)
Whats the purpose of negate and donil?
zero is trurthy on ruby, so you can do just!!(self =~ /^-?d+(.d*)?$/)
– Arnold Roa
Apr 11 '17 at 14:37
Using!!
certainly works. At least one Ruby style guide (github.com/bbatsov/ruby-style-guide) suggested avoiding!!
in favor of.nil?
for readability, but I've seen!!
used in popular repositories, and I think it is a fine way to convert to boolean. I've edited the answer.
– Mark Schneider
Apr 13 '17 at 2:52
add a comment |
As of Ruby 2.6.0, the numeric cast-methods have an optional exception
-argument [1]. This enables us to use the built-in methods without using exceptions as control flow:
Float('x') # => ArgumentError (invalid value for Float(): "x")
Float('x', exception: false) # => nil
Therefore, you don't have to define your own method, but can directly check variables like e.g.
if Float(my_var, exception: false)
# do something if my_var is a float
end
add a comment |
use the following function:
def is_numeric? val
return val.try(:to_f).try(:to_s) == val
end
so,
is_numeric? "1.2f"
= false
is_numeric? "1.2"
= true
is_numeric? "12f"
= false
is_numeric? "12"
= true
This will fail if val is"0"
. Also note that the method.try
isn't part of the Ruby core library and is only available if you're including ActiveSupport.
– GMA
Sep 17 '15 at 12:51
In fact, it also fails for"12"
, so your fourth example in this question is wrong."12.10"
and"12.00"
fail too.
– GMA
Sep 17 '15 at 12:52
add a comment |
How dumb is this solution?
def is_number?(i)
begin
i+0 == i
rescue TypeError
false
end
end
1
This is sub-optimal because using '.respond_to?(:+)' is always better then failing and catching an exception on a specific method (:+) call. This might also fail for a variety of reasons were the Regex and conversion methods don't.
– Sqeaky
Apr 28 '14 at 17:17
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f5661466%2ftest-if-string-is-a-number-in-ruby-on-rails%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
12 Answers
12
active
oldest
votes
12 Answers
12
active
oldest
votes
active
oldest
votes
active
oldest
votes
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
2
This is a bad idea. "330.346.11".to_f # => 330.346
– epochwolf
Nov 2 '11 at 23:15
11
There is noto_f
in the above, and Float() doesn't exhibit that behavior:Float("330.346.11")
raisesArgumentError: invalid value for Float(): "330.346.11"
– Jakob S
Nov 3 '11 at 10:29
6
If you use that patch, I'd rename it to numeric?, to stay in line with ruby naming conventions (Numeric classes inherit from Numeric, is_ prefixes are javaish).
– Konrad Reiche
Jun 24 '12 at 18:34
9
Not really relevant to the original question, but I'd probably put the code inlib/core_ext/string.rb
.
– Jakob S
Aug 7 '12 at 8:48
1
I don't think theis_number?(string)
bit works Ruby 1.9. Maybe that is part of Rails or 1.8?String.is_a?(Numeric)
works. See also stackoverflow.com/questions/2095493/….
– Ross Attrill
Jun 16 '14 at 7:10
|
show 7 more comments
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
2
This is a bad idea. "330.346.11".to_f # => 330.346
– epochwolf
Nov 2 '11 at 23:15
11
There is noto_f
in the above, and Float() doesn't exhibit that behavior:Float("330.346.11")
raisesArgumentError: invalid value for Float(): "330.346.11"
– Jakob S
Nov 3 '11 at 10:29
6
If you use that patch, I'd rename it to numeric?, to stay in line with ruby naming conventions (Numeric classes inherit from Numeric, is_ prefixes are javaish).
– Konrad Reiche
Jun 24 '12 at 18:34
9
Not really relevant to the original question, but I'd probably put the code inlib/core_ext/string.rb
.
– Jakob S
Aug 7 '12 at 8:48
1
I don't think theis_number?(string)
bit works Ruby 1.9. Maybe that is part of Rails or 1.8?String.is_a?(Numeric)
works. See also stackoverflow.com/questions/2095493/….
– Ross Attrill
Jun 16 '14 at 7:10
|
show 7 more comments
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
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
edited Jul 3 '15 at 11:44
Joshua Pinter
25.5k9145174
25.5k9145174
answered Apr 14 '11 at 10:13
Jakob SJakob S
16.1k23535
16.1k23535
2
This is a bad idea. "330.346.11".to_f # => 330.346
– epochwolf
Nov 2 '11 at 23:15
11
There is noto_f
in the above, and Float() doesn't exhibit that behavior:Float("330.346.11")
raisesArgumentError: invalid value for Float(): "330.346.11"
– Jakob S
Nov 3 '11 at 10:29
6
If you use that patch, I'd rename it to numeric?, to stay in line with ruby naming conventions (Numeric classes inherit from Numeric, is_ prefixes are javaish).
– Konrad Reiche
Jun 24 '12 at 18:34
9
Not really relevant to the original question, but I'd probably put the code inlib/core_ext/string.rb
.
– Jakob S
Aug 7 '12 at 8:48
1
I don't think theis_number?(string)
bit works Ruby 1.9. Maybe that is part of Rails or 1.8?String.is_a?(Numeric)
works. See also stackoverflow.com/questions/2095493/….
– Ross Attrill
Jun 16 '14 at 7:10
|
show 7 more comments
2
This is a bad idea. "330.346.11".to_f # => 330.346
– epochwolf
Nov 2 '11 at 23:15
11
There is noto_f
in the above, and Float() doesn't exhibit that behavior:Float("330.346.11")
raisesArgumentError: invalid value for Float(): "330.346.11"
– Jakob S
Nov 3 '11 at 10:29
6
If you use that patch, I'd rename it to numeric?, to stay in line with ruby naming conventions (Numeric classes inherit from Numeric, is_ prefixes are javaish).
– Konrad Reiche
Jun 24 '12 at 18:34
9
Not really relevant to the original question, but I'd probably put the code inlib/core_ext/string.rb
.
– Jakob S
Aug 7 '12 at 8:48
1
I don't think theis_number?(string)
bit works Ruby 1.9. Maybe that is part of Rails or 1.8?String.is_a?(Numeric)
works. See also stackoverflow.com/questions/2095493/….
– Ross Attrill
Jun 16 '14 at 7:10
2
2
This is a bad idea. "330.346.11".to_f # => 330.346
– epochwolf
Nov 2 '11 at 23:15
This is a bad idea. "330.346.11".to_f # => 330.346
– epochwolf
Nov 2 '11 at 23:15
11
11
There is no
to_f
in the above, and Float() doesn't exhibit that behavior: Float("330.346.11")
raises ArgumentError: invalid value for Float(): "330.346.11"
– Jakob S
Nov 3 '11 at 10:29
There is no
to_f
in the above, and Float() doesn't exhibit that behavior: Float("330.346.11")
raises ArgumentError: invalid value for Float(): "330.346.11"
– Jakob S
Nov 3 '11 at 10:29
6
6
If you use that patch, I'd rename it to numeric?, to stay in line with ruby naming conventions (Numeric classes inherit from Numeric, is_ prefixes are javaish).
– Konrad Reiche
Jun 24 '12 at 18:34
If you use that patch, I'd rename it to numeric?, to stay in line with ruby naming conventions (Numeric classes inherit from Numeric, is_ prefixes are javaish).
– Konrad Reiche
Jun 24 '12 at 18:34
9
9
Not really relevant to the original question, but I'd probably put the code in
lib/core_ext/string.rb
.– Jakob S
Aug 7 '12 at 8:48
Not really relevant to the original question, but I'd probably put the code in
lib/core_ext/string.rb
.– Jakob S
Aug 7 '12 at 8:48
1
1
I don't think the
is_number?(string)
bit works Ruby 1.9. Maybe that is part of Rails or 1.8? String.is_a?(Numeric)
works. See also stackoverflow.com/questions/2095493/….– Ross Attrill
Jun 16 '14 at 7:10
I don't think the
is_number?(string)
bit works Ruby 1.9. Maybe that is part of Rails or 1.8? String.is_a?(Numeric)
works. See also stackoverflow.com/questions/2095493/….– Ross Attrill
Jun 16 '14 at 7:10
|
show 7 more comments
class String
def numeric?
return true if self =~ /Ad+Z/
true if Float(self) rescue false
end
end
p "1".numeric? # => true
p "1.2".numeric? # => true
p "5.4e-29".numeric? # => true
p "12e20".numeric? # true
p "1a".numeric? # => false
p "1.2.3.4".numeric? # => false
11
/^d+$/
is not a safe regexp in Ruby,/Ad+Z/
is. (e.g. "42nsome text" would returntrue
)
– Timothee A
Sep 1 '14 at 15:18
To clarify on @TimotheeA's comment, it is safe to use/^d+$/
if dealing with lines but in this case it's about beginning and end of a string, thus/Ad+Z/
.
– Julio
Oct 9 '14 at 20:09
1
Shouldn't answers be edited to change the actual answer BY the responder? changing the answer in an edit if you're not the responder seems...possibly underhanded and should be out of bounds.
– jaydel
Jul 20 '16 at 15:43
Where should I put these codes?
– zx1986
Jul 7 '17 at 4:10
2
Z allows to have n at the end of the string, so "123n" will pass validation, regardless that it's not fully numeric. But if you use z then it will be more correct regexp: /Ad+z/
– SunnyMagadan
Aug 14 '17 at 9:14
add a comment |
class String
def numeric?
return true if self =~ /Ad+Z/
true if Float(self) rescue false
end
end
p "1".numeric? # => true
p "1.2".numeric? # => true
p "5.4e-29".numeric? # => true
p "12e20".numeric? # true
p "1a".numeric? # => false
p "1.2.3.4".numeric? # => false
11
/^d+$/
is not a safe regexp in Ruby,/Ad+Z/
is. (e.g. "42nsome text" would returntrue
)
– Timothee A
Sep 1 '14 at 15:18
To clarify on @TimotheeA's comment, it is safe to use/^d+$/
if dealing with lines but in this case it's about beginning and end of a string, thus/Ad+Z/
.
– Julio
Oct 9 '14 at 20:09
1
Shouldn't answers be edited to change the actual answer BY the responder? changing the answer in an edit if you're not the responder seems...possibly underhanded and should be out of bounds.
– jaydel
Jul 20 '16 at 15:43
Where should I put these codes?
– zx1986
Jul 7 '17 at 4:10
2
Z allows to have n at the end of the string, so "123n" will pass validation, regardless that it's not fully numeric. But if you use z then it will be more correct regexp: /Ad+z/
– SunnyMagadan
Aug 14 '17 at 9:14
add a comment |
class String
def numeric?
return true if self =~ /Ad+Z/
true if Float(self) rescue false
end
end
p "1".numeric? # => true
p "1.2".numeric? # => true
p "5.4e-29".numeric? # => true
p "12e20".numeric? # true
p "1a".numeric? # => false
p "1.2.3.4".numeric? # => false
class String
def numeric?
return true if self =~ /Ad+Z/
true if Float(self) rescue false
end
end
p "1".numeric? # => true
p "1.2".numeric? # => true
p "5.4e-29".numeric? # => true
p "12e20".numeric? # true
p "1a".numeric? # => false
p "1.2.3.4".numeric? # => false
edited May 1 '15 at 20:40
Marius Butuc
10.2k1868107
10.2k1868107
answered Jul 25 '12 at 16:02
hipertrackerhipertracker
2,1182212
2,1182212
11
/^d+$/
is not a safe regexp in Ruby,/Ad+Z/
is. (e.g. "42nsome text" would returntrue
)
– Timothee A
Sep 1 '14 at 15:18
To clarify on @TimotheeA's comment, it is safe to use/^d+$/
if dealing with lines but in this case it's about beginning and end of a string, thus/Ad+Z/
.
– Julio
Oct 9 '14 at 20:09
1
Shouldn't answers be edited to change the actual answer BY the responder? changing the answer in an edit if you're not the responder seems...possibly underhanded and should be out of bounds.
– jaydel
Jul 20 '16 at 15:43
Where should I put these codes?
– zx1986
Jul 7 '17 at 4:10
2
Z allows to have n at the end of the string, so "123n" will pass validation, regardless that it's not fully numeric. But if you use z then it will be more correct regexp: /Ad+z/
– SunnyMagadan
Aug 14 '17 at 9:14
add a comment |
11
/^d+$/
is not a safe regexp in Ruby,/Ad+Z/
is. (e.g. "42nsome text" would returntrue
)
– Timothee A
Sep 1 '14 at 15:18
To clarify on @TimotheeA's comment, it is safe to use/^d+$/
if dealing with lines but in this case it's about beginning and end of a string, thus/Ad+Z/
.
– Julio
Oct 9 '14 at 20:09
1
Shouldn't answers be edited to change the actual answer BY the responder? changing the answer in an edit if you're not the responder seems...possibly underhanded and should be out of bounds.
– jaydel
Jul 20 '16 at 15:43
Where should I put these codes?
– zx1986
Jul 7 '17 at 4:10
2
Z allows to have n at the end of the string, so "123n" will pass validation, regardless that it's not fully numeric. But if you use z then it will be more correct regexp: /Ad+z/
– SunnyMagadan
Aug 14 '17 at 9:14
11
11
/^d+$/
is not a safe regexp in Ruby, /Ad+Z/
is. (e.g. "42nsome text" would return true
)– Timothee A
Sep 1 '14 at 15:18
/^d+$/
is not a safe regexp in Ruby, /Ad+Z/
is. (e.g. "42nsome text" would return true
)– Timothee A
Sep 1 '14 at 15:18
To clarify on @TimotheeA's comment, it is safe to use
/^d+$/
if dealing with lines but in this case it's about beginning and end of a string, thus /Ad+Z/
.– Julio
Oct 9 '14 at 20:09
To clarify on @TimotheeA's comment, it is safe to use
/^d+$/
if dealing with lines but in this case it's about beginning and end of a string, thus /Ad+Z/
.– Julio
Oct 9 '14 at 20:09
1
1
Shouldn't answers be edited to change the actual answer BY the responder? changing the answer in an edit if you're not the responder seems...possibly underhanded and should be out of bounds.
– jaydel
Jul 20 '16 at 15:43
Shouldn't answers be edited to change the actual answer BY the responder? changing the answer in an edit if you're not the responder seems...possibly underhanded and should be out of bounds.
– jaydel
Jul 20 '16 at 15:43
Where should I put these codes?
– zx1986
Jul 7 '17 at 4:10
Where should I put these codes?
– zx1986
Jul 7 '17 at 4:10
2
2
Z allows to have n at the end of the string, so "123n" will pass validation, regardless that it's not fully numeric. But if you use z then it will be more correct regexp: /Ad+z/
– SunnyMagadan
Aug 14 '17 at 9:14
Z allows to have n at the end of the string, so "123n" will pass validation, regardless that it's not fully numeric. But if you use z then it will be more correct regexp: /Ad+z/
– SunnyMagadan
Aug 14 '17 at 9:14
add a comment |
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.
- If they are relatively uncommon casting is definitely fastest.
- If false cases are common and you are just checking for ints, comparison vs a transformed state is a good option.
- 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
add a comment |
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.
- If they are relatively uncommon casting is definitely fastest.
- If false cases are common and you are just checking for ints, comparison vs a transformed state is a good option.
- 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
add a comment |
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.
- If they are relatively uncommon casting is definitely fastest.
- If false cases are common and you are just checking for ints, comparison vs a transformed state is a good option.
- 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
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.
- If they are relatively uncommon casting is definitely fastest.
- If false cases are common and you are just checking for ints, comparison vs a transformed state is a good option.
- 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
answered Nov 8 '13 at 1:22
Matt SandersMatt Sanders
4,0772133
4,0772133
add a comment |
add a comment |
Relying on the raised exception is not the fastest, readable nor reliable solution.
I'd do the following :
my_string.should =~ /^[0-9]+$/
1
This only works for positive integers, however. Values like '-1', '0.0', or '1_000' all return false even though they are valid numeric values. You're looking at something like /^[-.0-9]+$/, but that erroneously accepts '--'.
– Jakob S
Apr 14 '11 at 11:03
10
From Rails 'validates_numericality_of': raw_value.to_s =~ /A[+-]?d+Z/
– Morten
Aug 17 '12 at 20:09
NoMethodError: undefined method `should' for "asd":String
– sergserg
Oct 9 '14 at 22:08
In the latest rspec, this becomesexpect(my_string).to match(/^[0-9]+$/)
– Damien MATHIEU
Oct 10 '14 at 8:55
I like:my_string =~ /A-?(d+)?.?d+Z/
it lets you do '.1', '-0.1', or '12' but not '' or '-' or '.'
– Josh
Sep 2 '16 at 0:05
|
show 1 more comment
Relying on the raised exception is not the fastest, readable nor reliable solution.
I'd do the following :
my_string.should =~ /^[0-9]+$/
1
This only works for positive integers, however. Values like '-1', '0.0', or '1_000' all return false even though they are valid numeric values. You're looking at something like /^[-.0-9]+$/, but that erroneously accepts '--'.
– Jakob S
Apr 14 '11 at 11:03
10
From Rails 'validates_numericality_of': raw_value.to_s =~ /A[+-]?d+Z/
– Morten
Aug 17 '12 at 20:09
NoMethodError: undefined method `should' for "asd":String
– sergserg
Oct 9 '14 at 22:08
In the latest rspec, this becomesexpect(my_string).to match(/^[0-9]+$/)
– Damien MATHIEU
Oct 10 '14 at 8:55
I like:my_string =~ /A-?(d+)?.?d+Z/
it lets you do '.1', '-0.1', or '12' but not '' or '-' or '.'
– Josh
Sep 2 '16 at 0:05
|
show 1 more comment
Relying on the raised exception is not the fastest, readable nor reliable solution.
I'd do the following :
my_string.should =~ /^[0-9]+$/
Relying on the raised exception is not the fastest, readable nor reliable solution.
I'd do the following :
my_string.should =~ /^[0-9]+$/
answered Apr 14 '11 at 10:20
Damien MATHIEUDamien MATHIEU
24k126586
24k126586
1
This only works for positive integers, however. Values like '-1', '0.0', or '1_000' all return false even though they are valid numeric values. You're looking at something like /^[-.0-9]+$/, but that erroneously accepts '--'.
– Jakob S
Apr 14 '11 at 11:03
10
From Rails 'validates_numericality_of': raw_value.to_s =~ /A[+-]?d+Z/
– Morten
Aug 17 '12 at 20:09
NoMethodError: undefined method `should' for "asd":String
– sergserg
Oct 9 '14 at 22:08
In the latest rspec, this becomesexpect(my_string).to match(/^[0-9]+$/)
– Damien MATHIEU
Oct 10 '14 at 8:55
I like:my_string =~ /A-?(d+)?.?d+Z/
it lets you do '.1', '-0.1', or '12' but not '' or '-' or '.'
– Josh
Sep 2 '16 at 0:05
|
show 1 more comment
1
This only works for positive integers, however. Values like '-1', '0.0', or '1_000' all return false even though they are valid numeric values. You're looking at something like /^[-.0-9]+$/, but that erroneously accepts '--'.
– Jakob S
Apr 14 '11 at 11:03
10
From Rails 'validates_numericality_of': raw_value.to_s =~ /A[+-]?d+Z/
– Morten
Aug 17 '12 at 20:09
NoMethodError: undefined method `should' for "asd":String
– sergserg
Oct 9 '14 at 22:08
In the latest rspec, this becomesexpect(my_string).to match(/^[0-9]+$/)
– Damien MATHIEU
Oct 10 '14 at 8:55
I like:my_string =~ /A-?(d+)?.?d+Z/
it lets you do '.1', '-0.1', or '12' but not '' or '-' or '.'
– Josh
Sep 2 '16 at 0:05
1
1
This only works for positive integers, however. Values like '-1', '0.0', or '1_000' all return false even though they are valid numeric values. You're looking at something like /^[-.0-9]+$/, but that erroneously accepts '--'.
– Jakob S
Apr 14 '11 at 11:03
This only works for positive integers, however. Values like '-1', '0.0', or '1_000' all return false even though they are valid numeric values. You're looking at something like /^[-.0-9]+$/, but that erroneously accepts '--'.
– Jakob S
Apr 14 '11 at 11:03
10
10
From Rails 'validates_numericality_of': raw_value.to_s =~ /A[+-]?d+Z/
– Morten
Aug 17 '12 at 20:09
From Rails 'validates_numericality_of': raw_value.to_s =~ /A[+-]?d+Z/
– Morten
Aug 17 '12 at 20:09
NoMethodError: undefined method `should' for "asd":String
– sergserg
Oct 9 '14 at 22:08
NoMethodError: undefined method `should' for "asd":String
– sergserg
Oct 9 '14 at 22:08
In the latest rspec, this becomes
expect(my_string).to match(/^[0-9]+$/)
– Damien MATHIEU
Oct 10 '14 at 8:55
In the latest rspec, this becomes
expect(my_string).to match(/^[0-9]+$/)
– Damien MATHIEU
Oct 10 '14 at 8:55
I like:
my_string =~ /A-?(d+)?.?d+Z/
it lets you do '.1', '-0.1', or '12' but not '' or '-' or '.'– Josh
Sep 2 '16 at 0:05
I like:
my_string =~ /A-?(d+)?.?d+Z/
it lets you do '.1', '-0.1', or '12' but not '' or '-' or '.'– Josh
Sep 2 '16 at 0:05
|
show 1 more comment
no you're just using it wrong. your is_number? has an argument. you called it without the argument
you should be doing is_number?(mystring)
Based on the is_number? method in the question, using is_a? is not giving the correct answer. Ifmystring
is indeed a String,mystring.is_a?(Integer)
will always be false. It looks like he wants a result likeis_number?("12.4") #=> true
– Jakob S
Apr 14 '11 at 10:15
mmm good point, lemme update that
– corroded
Apr 14 '11 at 10:20
Jakob S is correct. mystring is indeed always a string, but may be comprise of just numbers. perhaps my question should have been is_numeric? so as not to confuse the datatype
– Jamie Buchanan
Apr 14 '11 at 10:23
add a comment |
no you're just using it wrong. your is_number? has an argument. you called it without the argument
you should be doing is_number?(mystring)
Based on the is_number? method in the question, using is_a? is not giving the correct answer. Ifmystring
is indeed a String,mystring.is_a?(Integer)
will always be false. It looks like he wants a result likeis_number?("12.4") #=> true
– Jakob S
Apr 14 '11 at 10:15
mmm good point, lemme update that
– corroded
Apr 14 '11 at 10:20
Jakob S is correct. mystring is indeed always a string, but may be comprise of just numbers. perhaps my question should have been is_numeric? so as not to confuse the datatype
– Jamie Buchanan
Apr 14 '11 at 10:23
add a comment |
no you're just using it wrong. your is_number? has an argument. you called it without the argument
you should be doing is_number?(mystring)
no you're just using it wrong. your is_number? has an argument. you called it without the argument
you should be doing is_number?(mystring)
edited Apr 14 '11 at 10:22
answered Apr 14 '11 at 9:58
corrodedcorroded
15k1772128
15k1772128
Based on the is_number? method in the question, using is_a? is not giving the correct answer. Ifmystring
is indeed a String,mystring.is_a?(Integer)
will always be false. It looks like he wants a result likeis_number?("12.4") #=> true
– Jakob S
Apr 14 '11 at 10:15
mmm good point, lemme update that
– corroded
Apr 14 '11 at 10:20
Jakob S is correct. mystring is indeed always a string, but may be comprise of just numbers. perhaps my question should have been is_numeric? so as not to confuse the datatype
– Jamie Buchanan
Apr 14 '11 at 10:23
add a comment |
Based on the is_number? method in the question, using is_a? is not giving the correct answer. Ifmystring
is indeed a String,mystring.is_a?(Integer)
will always be false. It looks like he wants a result likeis_number?("12.4") #=> true
– Jakob S
Apr 14 '11 at 10:15
mmm good point, lemme update that
– corroded
Apr 14 '11 at 10:20
Jakob S is correct. mystring is indeed always a string, but may be comprise of just numbers. perhaps my question should have been is_numeric? so as not to confuse the datatype
– Jamie Buchanan
Apr 14 '11 at 10:23
Based on the is_number? method in the question, using is_a? is not giving the correct answer. If
mystring
is indeed a String, mystring.is_a?(Integer)
will always be false. It looks like he wants a result like is_number?("12.4") #=> true
– Jakob S
Apr 14 '11 at 10:15
Based on the is_number? method in the question, using is_a? is not giving the correct answer. If
mystring
is indeed a String, mystring.is_a?(Integer)
will always be false. It looks like he wants a result like is_number?("12.4") #=> true
– Jakob S
Apr 14 '11 at 10:15
mmm good point, lemme update that
– corroded
Apr 14 '11 at 10:20
mmm good point, lemme update that
– corroded
Apr 14 '11 at 10:20
Jakob S is correct. mystring is indeed always a string, but may be comprise of just numbers. perhaps my question should have been is_numeric? so as not to confuse the datatype
– Jamie Buchanan
Apr 14 '11 at 10:23
Jakob S is correct. mystring is indeed always a string, but may be comprise of just numbers. perhaps my question should have been is_numeric? so as not to confuse the datatype
– Jamie Buchanan
Apr 14 '11 at 10:23
add a comment |
Tl;dr: Use a regex approach. It is 39x faster than the rescue approach in the accepted answer and also handles cases like "1,000"
def regex_is_number? string
no_commas = string.gsub(',', '')
matches = no_commas.match(/-?d+(?:.d+)?/)
if !matches.nil? && matches.size == 1 && matches[0] == no_commas
true
else
false
end
end
--
The accepted answer by @Jakob S works for the most part, but catching exceptions can be really slow. In addition, the rescue approach fails on a string like "1,000".
Let's define the methods:
def rescue_is_number? string
true if Float(string) rescue false
end
def regex_is_number? string
no_commas = string.gsub(',', '')
matches = no_commas.match(/-?d+(?:.d+)?/)
if !matches.nil? && matches.size == 1 && matches[0] == no_commas
true
else
false
end
end
And now some test cases:
test_cases = {
true => ["5.5", "23", "-123", "1,234,123"],
false => ["hello", "99designs", "(123)456-7890"]
}
And a little code to run the test cases:
test_cases.each do |expected_answer, cases|
cases.each do |test_case|
if rescue_is_number?(test_case) != expected_answer
puts "**rescue_is_number? got #{test_case} wrong**"
else
puts "rescue_is_number? got #{test_case} right"
end
if regex_is_number?(test_case) != expected_answer
puts "**regex_is_number? got #{test_case} wrong**"
else
puts "regex_is_number? got #{test_case} right"
end
end
end
Here is the output of the test cases:
rescue_is_number? got 5.5 right
regex_is_number? got 5.5 right
rescue_is_number? got 23 right
regex_is_number? got 23 right
rescue_is_number? got -123 right
regex_is_number? got -123 right
**rescue_is_number? got 1,234,123 wrong**
regex_is_number? got 1,234,123 right
rescue_is_number? got hello right
regex_is_number? got hello right
rescue_is_number? got 99designs right
regex_is_number? got 99designs right
rescue_is_number? got (123)456-7890 right
regex_is_number? got (123)456-7890 right
Time to do some performance benchmarks:
Benchmark.ips do |x|
x.report("rescue") { test_cases.values.flatten.each { |c| rescue_is_number? c } }
x.report("regex") { test_cases.values.flatten.each { |c| regex_is_number? c } }
x.compare!
end
And the results:
Calculating -------------------------------------
rescue 128.000 i/100ms
regex 4.649k i/100ms
-------------------------------------------------
rescue 1.348k (±16.8%) i/s - 6.656k
regex 52.113k (± 7.8%) i/s - 260.344k
Comparison:
regex: 52113.3 i/s
rescue: 1347.5 i/s - 38.67x slower
Thanks for the benchmark. The accepted answer has the advantage of accepting inputs like5.4e-29
. I guess your regex could be tweaked to accept those also.
– Jodi
Feb 24 '16 at 16:27
1
Handling cases like 1,000 is really hard, since it depends on user intention. There are many, many ways for humans to format numbers. Is 1,000 about equal to 1000, or about equal to 1? Most of the world says it's about 1, not a way to show the integer 1000.
– James Moore
Feb 25 '17 at 18:59
add a comment |
Tl;dr: Use a regex approach. It is 39x faster than the rescue approach in the accepted answer and also handles cases like "1,000"
def regex_is_number? string
no_commas = string.gsub(',', '')
matches = no_commas.match(/-?d+(?:.d+)?/)
if !matches.nil? && matches.size == 1 && matches[0] == no_commas
true
else
false
end
end
--
The accepted answer by @Jakob S works for the most part, but catching exceptions can be really slow. In addition, the rescue approach fails on a string like "1,000".
Let's define the methods:
def rescue_is_number? string
true if Float(string) rescue false
end
def regex_is_number? string
no_commas = string.gsub(',', '')
matches = no_commas.match(/-?d+(?:.d+)?/)
if !matches.nil? && matches.size == 1 && matches[0] == no_commas
true
else
false
end
end
And now some test cases:
test_cases = {
true => ["5.5", "23", "-123", "1,234,123"],
false => ["hello", "99designs", "(123)456-7890"]
}
And a little code to run the test cases:
test_cases.each do |expected_answer, cases|
cases.each do |test_case|
if rescue_is_number?(test_case) != expected_answer
puts "**rescue_is_number? got #{test_case} wrong**"
else
puts "rescue_is_number? got #{test_case} right"
end
if regex_is_number?(test_case) != expected_answer
puts "**regex_is_number? got #{test_case} wrong**"
else
puts "regex_is_number? got #{test_case} right"
end
end
end
Here is the output of the test cases:
rescue_is_number? got 5.5 right
regex_is_number? got 5.5 right
rescue_is_number? got 23 right
regex_is_number? got 23 right
rescue_is_number? got -123 right
regex_is_number? got -123 right
**rescue_is_number? got 1,234,123 wrong**
regex_is_number? got 1,234,123 right
rescue_is_number? got hello right
regex_is_number? got hello right
rescue_is_number? got 99designs right
regex_is_number? got 99designs right
rescue_is_number? got (123)456-7890 right
regex_is_number? got (123)456-7890 right
Time to do some performance benchmarks:
Benchmark.ips do |x|
x.report("rescue") { test_cases.values.flatten.each { |c| rescue_is_number? c } }
x.report("regex") { test_cases.values.flatten.each { |c| regex_is_number? c } }
x.compare!
end
And the results:
Calculating -------------------------------------
rescue 128.000 i/100ms
regex 4.649k i/100ms
-------------------------------------------------
rescue 1.348k (±16.8%) i/s - 6.656k
regex 52.113k (± 7.8%) i/s - 260.344k
Comparison:
regex: 52113.3 i/s
rescue: 1347.5 i/s - 38.67x slower
Thanks for the benchmark. The accepted answer has the advantage of accepting inputs like5.4e-29
. I guess your regex could be tweaked to accept those also.
– Jodi
Feb 24 '16 at 16:27
1
Handling cases like 1,000 is really hard, since it depends on user intention. There are many, many ways for humans to format numbers. Is 1,000 about equal to 1000, or about equal to 1? Most of the world says it's about 1, not a way to show the integer 1000.
– James Moore
Feb 25 '17 at 18:59
add a comment |
Tl;dr: Use a regex approach. It is 39x faster than the rescue approach in the accepted answer and also handles cases like "1,000"
def regex_is_number? string
no_commas = string.gsub(',', '')
matches = no_commas.match(/-?d+(?:.d+)?/)
if !matches.nil? && matches.size == 1 && matches[0] == no_commas
true
else
false
end
end
--
The accepted answer by @Jakob S works for the most part, but catching exceptions can be really slow. In addition, the rescue approach fails on a string like "1,000".
Let's define the methods:
def rescue_is_number? string
true if Float(string) rescue false
end
def regex_is_number? string
no_commas = string.gsub(',', '')
matches = no_commas.match(/-?d+(?:.d+)?/)
if !matches.nil? && matches.size == 1 && matches[0] == no_commas
true
else
false
end
end
And now some test cases:
test_cases = {
true => ["5.5", "23", "-123", "1,234,123"],
false => ["hello", "99designs", "(123)456-7890"]
}
And a little code to run the test cases:
test_cases.each do |expected_answer, cases|
cases.each do |test_case|
if rescue_is_number?(test_case) != expected_answer
puts "**rescue_is_number? got #{test_case} wrong**"
else
puts "rescue_is_number? got #{test_case} right"
end
if regex_is_number?(test_case) != expected_answer
puts "**regex_is_number? got #{test_case} wrong**"
else
puts "regex_is_number? got #{test_case} right"
end
end
end
Here is the output of the test cases:
rescue_is_number? got 5.5 right
regex_is_number? got 5.5 right
rescue_is_number? got 23 right
regex_is_number? got 23 right
rescue_is_number? got -123 right
regex_is_number? got -123 right
**rescue_is_number? got 1,234,123 wrong**
regex_is_number? got 1,234,123 right
rescue_is_number? got hello right
regex_is_number? got hello right
rescue_is_number? got 99designs right
regex_is_number? got 99designs right
rescue_is_number? got (123)456-7890 right
regex_is_number? got (123)456-7890 right
Time to do some performance benchmarks:
Benchmark.ips do |x|
x.report("rescue") { test_cases.values.flatten.each { |c| rescue_is_number? c } }
x.report("regex") { test_cases.values.flatten.each { |c| regex_is_number? c } }
x.compare!
end
And the results:
Calculating -------------------------------------
rescue 128.000 i/100ms
regex 4.649k i/100ms
-------------------------------------------------
rescue 1.348k (±16.8%) i/s - 6.656k
regex 52.113k (± 7.8%) i/s - 260.344k
Comparison:
regex: 52113.3 i/s
rescue: 1347.5 i/s - 38.67x slower
Tl;dr: Use a regex approach. It is 39x faster than the rescue approach in the accepted answer and also handles cases like "1,000"
def regex_is_number? string
no_commas = string.gsub(',', '')
matches = no_commas.match(/-?d+(?:.d+)?/)
if !matches.nil? && matches.size == 1 && matches[0] == no_commas
true
else
false
end
end
--
The accepted answer by @Jakob S works for the most part, but catching exceptions can be really slow. In addition, the rescue approach fails on a string like "1,000".
Let's define the methods:
def rescue_is_number? string
true if Float(string) rescue false
end
def regex_is_number? string
no_commas = string.gsub(',', '')
matches = no_commas.match(/-?d+(?:.d+)?/)
if !matches.nil? && matches.size == 1 && matches[0] == no_commas
true
else
false
end
end
And now some test cases:
test_cases = {
true => ["5.5", "23", "-123", "1,234,123"],
false => ["hello", "99designs", "(123)456-7890"]
}
And a little code to run the test cases:
test_cases.each do |expected_answer, cases|
cases.each do |test_case|
if rescue_is_number?(test_case) != expected_answer
puts "**rescue_is_number? got #{test_case} wrong**"
else
puts "rescue_is_number? got #{test_case} right"
end
if regex_is_number?(test_case) != expected_answer
puts "**regex_is_number? got #{test_case} wrong**"
else
puts "regex_is_number? got #{test_case} right"
end
end
end
Here is the output of the test cases:
rescue_is_number? got 5.5 right
regex_is_number? got 5.5 right
rescue_is_number? got 23 right
regex_is_number? got 23 right
rescue_is_number? got -123 right
regex_is_number? got -123 right
**rescue_is_number? got 1,234,123 wrong**
regex_is_number? got 1,234,123 right
rescue_is_number? got hello right
regex_is_number? got hello right
rescue_is_number? got 99designs right
regex_is_number? got 99designs right
rescue_is_number? got (123)456-7890 right
regex_is_number? got (123)456-7890 right
Time to do some performance benchmarks:
Benchmark.ips do |x|
x.report("rescue") { test_cases.values.flatten.each { |c| rescue_is_number? c } }
x.report("regex") { test_cases.values.flatten.each { |c| regex_is_number? c } }
x.compare!
end
And the results:
Calculating -------------------------------------
rescue 128.000 i/100ms
regex 4.649k i/100ms
-------------------------------------------------
rescue 1.348k (±16.8%) i/s - 6.656k
regex 52.113k (± 7.8%) i/s - 260.344k
Comparison:
regex: 52113.3 i/s
rescue: 1347.5 i/s - 38.67x slower
answered Feb 19 '16 at 23:07
pthammpthamm
1,5421814
1,5421814
Thanks for the benchmark. The accepted answer has the advantage of accepting inputs like5.4e-29
. I guess your regex could be tweaked to accept those also.
– Jodi
Feb 24 '16 at 16:27
1
Handling cases like 1,000 is really hard, since it depends on user intention. There are many, many ways for humans to format numbers. Is 1,000 about equal to 1000, or about equal to 1? Most of the world says it's about 1, not a way to show the integer 1000.
– James Moore
Feb 25 '17 at 18:59
add a comment |
Thanks for the benchmark. The accepted answer has the advantage of accepting inputs like5.4e-29
. I guess your regex could be tweaked to accept those also.
– Jodi
Feb 24 '16 at 16:27
1
Handling cases like 1,000 is really hard, since it depends on user intention. There are many, many ways for humans to format numbers. Is 1,000 about equal to 1000, or about equal to 1? Most of the world says it's about 1, not a way to show the integer 1000.
– James Moore
Feb 25 '17 at 18:59
Thanks for the benchmark. The accepted answer has the advantage of accepting inputs like
5.4e-29
. I guess your regex could be tweaked to accept those also.– Jodi
Feb 24 '16 at 16:27
Thanks for the benchmark. The accepted answer has the advantage of accepting inputs like
5.4e-29
. I guess your regex could be tweaked to accept those also.– Jodi
Feb 24 '16 at 16:27
1
1
Handling cases like 1,000 is really hard, since it depends on user intention. There are many, many ways for humans to format numbers. Is 1,000 about equal to 1000, or about equal to 1? Most of the world says it's about 1, not a way to show the integer 1000.
– James Moore
Feb 25 '17 at 18:59
Handling cases like 1,000 is really hard, since it depends on user intention. There are many, many ways for humans to format numbers. Is 1,000 about equal to 1000, or about equal to 1? Most of the world says it's about 1, not a way to show the integer 1000.
– James Moore
Feb 25 '17 at 18:59
add a comment |
this is how i do it, but i think too there must be a better way
object.to_i.to_s == object || object.to_f.to_s == object
4
It does not recognize floating notation, e.g. 1.2e+35.
– hipertracker
Jul 25 '12 at 16:13
add a comment |
this is how i do it, but i think too there must be a better way
object.to_i.to_s == object || object.to_f.to_s == object
4
It does not recognize floating notation, e.g. 1.2e+35.
– hipertracker
Jul 25 '12 at 16:13
add a comment |
this is how i do it, but i think too there must be a better way
object.to_i.to_s == object || object.to_f.to_s == object
this is how i do it, but i think too there must be a better way
object.to_i.to_s == object || object.to_f.to_s == object
answered Apr 14 '11 at 9:58
antpawantpaw
10k84278
10k84278
4
It does not recognize floating notation, e.g. 1.2e+35.
– hipertracker
Jul 25 '12 at 16:13
add a comment |
4
It does not recognize floating notation, e.g. 1.2e+35.
– hipertracker
Jul 25 '12 at 16:13
4
4
It does not recognize floating notation, e.g. 1.2e+35.
– hipertracker
Jul 25 '12 at 16:13
It does not recognize floating notation, e.g. 1.2e+35.
– hipertracker
Jul 25 '12 at 16:13
add a comment |
In rails 4, you need to put
require File.expand_path('../../lib', __FILE__) + '/ext/string'
in your config/application.rb
1
actually you don't need to do this, you could just put string.rb in "initializers" and it works!
– mahatmanich
Jun 16 '14 at 8:32
That's it! so cool!
– zx1986
Jul 7 '17 at 6:14
add a comment |
In rails 4, you need to put
require File.expand_path('../../lib', __FILE__) + '/ext/string'
in your config/application.rb
1
actually you don't need to do this, you could just put string.rb in "initializers" and it works!
– mahatmanich
Jun 16 '14 at 8:32
That's it! so cool!
– zx1986
Jul 7 '17 at 6:14
add a comment |
In rails 4, you need to put
require File.expand_path('../../lib', __FILE__) + '/ext/string'
in your config/application.rb
In rails 4, you need to put
require File.expand_path('../../lib', __FILE__) + '/ext/string'
in your config/application.rb
answered May 19 '14 at 4:57
jcyejcye
515
515
1
actually you don't need to do this, you could just put string.rb in "initializers" and it works!
– mahatmanich
Jun 16 '14 at 8:32
That's it! so cool!
– zx1986
Jul 7 '17 at 6:14
add a comment |
1
actually you don't need to do this, you could just put string.rb in "initializers" and it works!
– mahatmanich
Jun 16 '14 at 8:32
That's it! so cool!
– zx1986
Jul 7 '17 at 6:14
1
1
actually you don't need to do this, you could just put string.rb in "initializers" and it works!
– mahatmanich
Jun 16 '14 at 8:32
actually you don't need to do this, you could just put string.rb in "initializers" and it works!
– mahatmanich
Jun 16 '14 at 8:32
That's it! so cool!
– zx1986
Jul 7 '17 at 6:14
That's it! so cool!
– zx1986
Jul 7 '17 at 6:14
add a comment |
If you prefer not to use exceptions as part of the logic, you might try this:
class String
def numeric?
!!(self =~ /^-?d+(.d*)?$/)
end
end
Or, if you want it to work across all object classes, replace class String
with class Object
an convert self to a string: !!(self.to_s =~ /^-?d+(.d*)?$/)
Whats the purpose of negate and donil?
zero is trurthy on ruby, so you can do just!!(self =~ /^-?d+(.d*)?$/)
– Arnold Roa
Apr 11 '17 at 14:37
Using!!
certainly works. At least one Ruby style guide (github.com/bbatsov/ruby-style-guide) suggested avoiding!!
in favor of.nil?
for readability, but I've seen!!
used in popular repositories, and I think it is a fine way to convert to boolean. I've edited the answer.
– Mark Schneider
Apr 13 '17 at 2:52
add a comment |
If you prefer not to use exceptions as part of the logic, you might try this:
class String
def numeric?
!!(self =~ /^-?d+(.d*)?$/)
end
end
Or, if you want it to work across all object classes, replace class String
with class Object
an convert self to a string: !!(self.to_s =~ /^-?d+(.d*)?$/)
Whats the purpose of negate and donil?
zero is trurthy on ruby, so you can do just!!(self =~ /^-?d+(.d*)?$/)
– Arnold Roa
Apr 11 '17 at 14:37
Using!!
certainly works. At least one Ruby style guide (github.com/bbatsov/ruby-style-guide) suggested avoiding!!
in favor of.nil?
for readability, but I've seen!!
used in popular repositories, and I think it is a fine way to convert to boolean. I've edited the answer.
– Mark Schneider
Apr 13 '17 at 2:52
add a comment |
If you prefer not to use exceptions as part of the logic, you might try this:
class String
def numeric?
!!(self =~ /^-?d+(.d*)?$/)
end
end
Or, if you want it to work across all object classes, replace class String
with class Object
an convert self to a string: !!(self.to_s =~ /^-?d+(.d*)?$/)
If you prefer not to use exceptions as part of the logic, you might try this:
class String
def numeric?
!!(self =~ /^-?d+(.d*)?$/)
end
end
Or, if you want it to work across all object classes, replace class String
with class Object
an convert self to a string: !!(self.to_s =~ /^-?d+(.d*)?$/)
edited Apr 13 '17 at 2:50
answered Jun 7 '13 at 4:20
Mark SchneiderMark Schneider
13519
13519
Whats the purpose of negate and donil?
zero is trurthy on ruby, so you can do just!!(self =~ /^-?d+(.d*)?$/)
– Arnold Roa
Apr 11 '17 at 14:37
Using!!
certainly works. At least one Ruby style guide (github.com/bbatsov/ruby-style-guide) suggested avoiding!!
in favor of.nil?
for readability, but I've seen!!
used in popular repositories, and I think it is a fine way to convert to boolean. I've edited the answer.
– Mark Schneider
Apr 13 '17 at 2:52
add a comment |
Whats the purpose of negate and donil?
zero is trurthy on ruby, so you can do just!!(self =~ /^-?d+(.d*)?$/)
– Arnold Roa
Apr 11 '17 at 14:37
Using!!
certainly works. At least one Ruby style guide (github.com/bbatsov/ruby-style-guide) suggested avoiding!!
in favor of.nil?
for readability, but I've seen!!
used in popular repositories, and I think it is a fine way to convert to boolean. I've edited the answer.
– Mark Schneider
Apr 13 '17 at 2:52
Whats the purpose of negate and do
nil?
zero is trurthy on ruby, so you can do just !!(self =~ /^-?d+(.d*)?$/)
– Arnold Roa
Apr 11 '17 at 14:37
Whats the purpose of negate and do
nil?
zero is trurthy on ruby, so you can do just !!(self =~ /^-?d+(.d*)?$/)
– Arnold Roa
Apr 11 '17 at 14:37
Using
!!
certainly works. At least one Ruby style guide (github.com/bbatsov/ruby-style-guide) suggested avoiding !!
in favor of .nil?
for readability, but I've seen !!
used in popular repositories, and I think it is a fine way to convert to boolean. I've edited the answer.– Mark Schneider
Apr 13 '17 at 2:52
Using
!!
certainly works. At least one Ruby style guide (github.com/bbatsov/ruby-style-guide) suggested avoiding !!
in favor of .nil?
for readability, but I've seen !!
used in popular repositories, and I think it is a fine way to convert to boolean. I've edited the answer.– Mark Schneider
Apr 13 '17 at 2:52
add a comment |
As of Ruby 2.6.0, the numeric cast-methods have an optional exception
-argument [1]. This enables us to use the built-in methods without using exceptions as control flow:
Float('x') # => ArgumentError (invalid value for Float(): "x")
Float('x', exception: false) # => nil
Therefore, you don't have to define your own method, but can directly check variables like e.g.
if Float(my_var, exception: false)
# do something if my_var is a float
end
add a comment |
As of Ruby 2.6.0, the numeric cast-methods have an optional exception
-argument [1]. This enables us to use the built-in methods without using exceptions as control flow:
Float('x') # => ArgumentError (invalid value for Float(): "x")
Float('x', exception: false) # => nil
Therefore, you don't have to define your own method, but can directly check variables like e.g.
if Float(my_var, exception: false)
# do something if my_var is a float
end
add a comment |
As of Ruby 2.6.0, the numeric cast-methods have an optional exception
-argument [1]. This enables us to use the built-in methods without using exceptions as control flow:
Float('x') # => ArgumentError (invalid value for Float(): "x")
Float('x', exception: false) # => nil
Therefore, you don't have to define your own method, but can directly check variables like e.g.
if Float(my_var, exception: false)
# do something if my_var is a float
end
As of Ruby 2.6.0, the numeric cast-methods have an optional exception
-argument [1]. This enables us to use the built-in methods without using exceptions as control flow:
Float('x') # => ArgumentError (invalid value for Float(): "x")
Float('x', exception: false) # => nil
Therefore, you don't have to define your own method, but can directly check variables like e.g.
if Float(my_var, exception: false)
# do something if my_var is a float
end
answered Jan 3 at 12:59
TimitryTimitry
431614
431614
add a comment |
add a comment |
use the following function:
def is_numeric? val
return val.try(:to_f).try(:to_s) == val
end
so,
is_numeric? "1.2f"
= false
is_numeric? "1.2"
= true
is_numeric? "12f"
= false
is_numeric? "12"
= true
This will fail if val is"0"
. Also note that the method.try
isn't part of the Ruby core library and is only available if you're including ActiveSupport.
– GMA
Sep 17 '15 at 12:51
In fact, it also fails for"12"
, so your fourth example in this question is wrong."12.10"
and"12.00"
fail too.
– GMA
Sep 17 '15 at 12:52
add a comment |
use the following function:
def is_numeric? val
return val.try(:to_f).try(:to_s) == val
end
so,
is_numeric? "1.2f"
= false
is_numeric? "1.2"
= true
is_numeric? "12f"
= false
is_numeric? "12"
= true
This will fail if val is"0"
. Also note that the method.try
isn't part of the Ruby core library and is only available if you're including ActiveSupport.
– GMA
Sep 17 '15 at 12:51
In fact, it also fails for"12"
, so your fourth example in this question is wrong."12.10"
and"12.00"
fail too.
– GMA
Sep 17 '15 at 12:52
add a comment |
use the following function:
def is_numeric? val
return val.try(:to_f).try(:to_s) == val
end
so,
is_numeric? "1.2f"
= false
is_numeric? "1.2"
= true
is_numeric? "12f"
= false
is_numeric? "12"
= true
use the following function:
def is_numeric? val
return val.try(:to_f).try(:to_s) == val
end
so,
is_numeric? "1.2f"
= false
is_numeric? "1.2"
= true
is_numeric? "12f"
= false
is_numeric? "12"
= true
answered Dec 22 '14 at 12:19
Rajesh PaulRajesh Paul
3,88562743
3,88562743
This will fail if val is"0"
. Also note that the method.try
isn't part of the Ruby core library and is only available if you're including ActiveSupport.
– GMA
Sep 17 '15 at 12:51
In fact, it also fails for"12"
, so your fourth example in this question is wrong."12.10"
and"12.00"
fail too.
– GMA
Sep 17 '15 at 12:52
add a comment |
This will fail if val is"0"
. Also note that the method.try
isn't part of the Ruby core library and is only available if you're including ActiveSupport.
– GMA
Sep 17 '15 at 12:51
In fact, it also fails for"12"
, so your fourth example in this question is wrong."12.10"
and"12.00"
fail too.
– GMA
Sep 17 '15 at 12:52
This will fail if val is
"0"
. Also note that the method .try
isn't part of the Ruby core library and is only available if you're including ActiveSupport.– GMA
Sep 17 '15 at 12:51
This will fail if val is
"0"
. Also note that the method .try
isn't part of the Ruby core library and is only available if you're including ActiveSupport.– GMA
Sep 17 '15 at 12:51
In fact, it also fails for
"12"
, so your fourth example in this question is wrong. "12.10"
and "12.00"
fail too.– GMA
Sep 17 '15 at 12:52
In fact, it also fails for
"12"
, so your fourth example in this question is wrong. "12.10"
and "12.00"
fail too.– GMA
Sep 17 '15 at 12:52
add a comment |
How dumb is this solution?
def is_number?(i)
begin
i+0 == i
rescue TypeError
false
end
end
1
This is sub-optimal because using '.respond_to?(:+)' is always better then failing and catching an exception on a specific method (:+) call. This might also fail for a variety of reasons were the Regex and conversion methods don't.
– Sqeaky
Apr 28 '14 at 17:17
add a comment |
How dumb is this solution?
def is_number?(i)
begin
i+0 == i
rescue TypeError
false
end
end
1
This is sub-optimal because using '.respond_to?(:+)' is always better then failing and catching an exception on a specific method (:+) call. This might also fail for a variety of reasons were the Regex and conversion methods don't.
– Sqeaky
Apr 28 '14 at 17:17
add a comment |
How dumb is this solution?
def is_number?(i)
begin
i+0 == i
rescue TypeError
false
end
end
How dumb is this solution?
def is_number?(i)
begin
i+0 == i
rescue TypeError
false
end
end
answered Oct 6 '13 at 12:16
donvnielsendonvnielsen
837
837
1
This is sub-optimal because using '.respond_to?(:+)' is always better then failing and catching an exception on a specific method (:+) call. This might also fail for a variety of reasons were the Regex and conversion methods don't.
– Sqeaky
Apr 28 '14 at 17:17
add a comment |
1
This is sub-optimal because using '.respond_to?(:+)' is always better then failing and catching an exception on a specific method (:+) call. This might also fail for a variety of reasons were the Regex and conversion methods don't.
– Sqeaky
Apr 28 '14 at 17:17
1
1
This is sub-optimal because using '.respond_to?(:+)' is always better then failing and catching an exception on a specific method (:+) call. This might also fail for a variety of reasons were the Regex and conversion methods don't.
– Sqeaky
Apr 28 '14 at 17:17
This is sub-optimal because using '.respond_to?(:+)' is always better then failing and catching an exception on a specific method (:+) call. This might also fail for a variety of reasons were the Regex and conversion methods don't.
– Sqeaky
Apr 28 '14 at 17:17
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f5661466%2ftest-if-string-is-a-number-in-ruby-on-rails%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
4
I know a lot of people are here because of codeschool's Rails for Zombies Testing class. Just wait for him to keep explaining. The tests aren't supposed to pass --- its OK to have you test fail in error, you can always patch rails to invent methods such as self.is_number?
– boulder_ruby
Feb 28 '13 at 19:33
The accepted answer fails on cases like "1,000" and is a 39x slower than using a regex approach. See my answer below.
– pthamm
Feb 19 '16 at 23:10