# Basic Question: How do you check to see if gets is a number?

**URL:** <https://www.ruby-forum.com/t/basic-question-how-do-you-check-to-see-if-gets-is-a-number/191393>\
**Category:** Ruby\
**Created:** [July 11, 2010, 6:34pm UTC](https://www.ruby-forum.com/t/basic-question-how-do-you-check-to-see-if-gets-is-a-number/191393 "2010-07-11T18:34:54Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![adambeazley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/5f9b8f/32.png) [@adambeazley](https://www.ruby-forum.com/u/adambeazley)\
**Post date:** [July 11, 2010, 6:34pm UTC](https://www.ruby-forum.com/t/basic-question-how-do-you-check-to-see-if-gets-is-a-number/191393/1 "2010-07-11T18:34:54Z")

</div>

I wrote a basic script that asks for your age then converts it into  
months, days and weeks old. I wanted to add some sort of control so that  
it would return an error if you didn’t enter a number but rather a word  
or a letter or something.

Can you please give me pointers? I’ve done quite a bit of Googling and  
am not sure how to do this. When I enter a number or a letter it  
returns the else statement. Please help! See attached for example of it  
being run.

Here’s my script below:

# Basic Program to ask for a persons age and out put that in months

# Writen by Adam B. on 2010-07-11

# Define verables

months = 12

# Question that asks for your age

puts “Hello, in the field below please enter your age:”

# Get’s is the ruby method that asks for your age, it gets the

information from # the terminal when you type  
age = gets

# This checks to see if you input a number, if you do it outputs the

results

# if you don’t it asks you for it in a numerical format eg 21

if ( age.to\_f.to\_s == true )  
monthsold = age.to\_i \* months.to\_i  
puts ‘You are ’ + monthsold.to\_s + ’ months old’  
else  
puts ‘Error, please enter a number!’  
end

---

<div class="post-metadata">

**Author:** ![adambeazley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/5f9b8f/32.png) [@adambeazley](https://www.ruby-forum.com/u/adambeazley)\
**Post date:** [July 11, 2010, 7:03pm UTC](https://www.ruby-forum.com/t/basic-question-how-do-you-check-to-see-if-gets-is-a-number/191393/2 "2010-07-11T19:03:28Z")

</div>

On Sunday 11 July 2010, Adam B. wrote:

> |Here’s my script below:  
> |# Get’s is the ruby method that asks for your age, it gets the  
> | puts ‘Error, please enter a number!’  
> | end  
> |

There are a couple of errors in your code. First of all, in ruby you  
never  
compare something with true (or false) in an if. That’s because the only  
value  
which is == to true is… true (and the only value which is == to false  
is  
false). This explains why you keep getting the error message: you’re  
comparing  
the string returned by the to\_s method with true. These are different,  
so the  
== operator returns false, which leads to executing the “else” branch of  
the  
if.

The if statement in ruby works in the following way: it checks what  
value the  
condition evaluates to. If it’s the _false_ object or the _nil_ object,  
then  
the “else” branch is executed. All other values cause the “if” branch to  
be  
executed. So, to test whether a condition is true, you simply write:

if some\_expression  
…  
else  
…  
end

where some\_expression is any piece of ruby code which doesn’t evaluate  
to  
false or nil.

The first step to fix your code, then, is to remove everything left to  
the  
to\_s inside the condition. You can also remove the brackets, as they’re  
not  
needed around the condition in an if statement.

This leaves us with:

if age.to\_f.to\_s

Now, the to\_s method of any object will return a string which ruby will  
always  
consider a true value. This means that now we have the opposite problem  
we had  
before: the error message is never shown. Removing the to\_s would help  
if  
String#to\_f didn’t return 0.0 (which is also considered a true value) in  
case  
the string doesn’t represent a number.

The simplest way to tell whether a string represents a number is to use  
the  
Kernel#Float method, or Kernel#Integer if you want an integer number.  
Unlike  
String#to\_f and String#to\_i, which always return a number, these methods  
raise  
an exception if the string can’t be translated to a number. So you can  
write:

#gets returns the string with a trailing newline, so you have to remove  
it  
age = gets.strip

age\_numeric = begin Integer(age)  
rescue ArgumentError  
puts “Enter a valid number”  
exit  
end  
#months is already an integer, so there’s no need to call to\_i on it  
monthsold = age\_numeric \* months

I hope this helps

Stefano

---

<div class="post-metadata">

**Author:** ![adambeazley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/5f9b8f/32.png) [@adambeazley](https://www.ruby-forum.com/u/adambeazley)\
**Post date:** [July 11, 2010, 7:05pm UTC](https://www.ruby-forum.com/t/basic-question-how-do-you-check-to-see-if-gets-is-a-number/191393/3 "2010-07-11T19:05:49Z")

</div>

On Sun, Jul 11, 2010 at 12:34 PM, Adam B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> if ( age.to\_f.to\_s == true )

This will NEVER happen.

age.to\_f converts the string to a float. If the string isn’t valid it  
returns 0.0.

age.to\_f.to\_s will ALWAYS be a string, and will never == true

> monthsold = age.to\_i \* months.to\_i  
> puts ‘You are ’ + monthsold.to\_s + ’ months old’  
> else

Now I’m not sure whether or not you really want to accept an age as a  
float, or just an integer, but you need to do something else to  
validate the string.

One way would be to use a regular expression, e.g. something like

if age =~ /^d+$/ # for an integer  
or  
if age =~/^d+(|.\d\*)$/ # for a float

These are fairly strict in what they’ll accept, you might want  
slightly different regular expressions, particularly if you really  
want a float.

Or use either Kernel#Integer or Kernel#Float which raise an error if  
they don’t like the string:

float\_age = Float(age) rescue nil  
if float\_age  
#…

HTH

–  
Rick DeNatale

Blog: [http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)  
Github: [rubyredrick (Rick DeNatale) · GitHub](http://github.com/rubyredrick)  
Twitter: @RickDeNatale  
WWR: [http://www.workingwithrails.com/person/9021-rick-denatale](http://www.workingwithrails.com/person/9021-rick-denatale)  
LinkedIn: [http://www.linkedin.com/in/rickdenatale](http://www.linkedin.com/in/rickdenatale)

---

<div class="post-metadata">

**Author:** ![adambeazley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/5f9b8f/32.png) [@adambeazley](https://www.ruby-forum.com/u/adambeazley)\
**Post date:** [July 11, 2010, 7:35pm UTC](https://www.ruby-forum.com/t/basic-question-how-do-you-check-to-see-if-gets-is-a-number/191393/4 "2010-07-11T19:35:40Z")

</div>

In article [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid),  
Adam B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> if ( age.to\_f.to\_s == true )

What do you expect this to evaluate to? Instead of “true”, did you mean  
to use “age” (i.e., compare the original string with a reconverted  
number string)? Even that test will fail:

irb(main):003:0\> “42”.to\_f.to\_s == “42”  
=\> false

Barring full-blown input validation, the simple solution is to note that  
non-numbers get converted to 0. That also happens to be an age you can  
likely reject. Run with it.

---

<div class="post-metadata">

**Author:** ![adambeazley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/5f9b8f/32.png) [@adambeazley](https://www.ruby-forum.com/u/adambeazley)\
**Post date:** [July 11, 2010, 9:38pm UTC](https://www.ruby-forum.com/t/basic-question-how-do-you-check-to-see-if-gets-is-a-number/191393/5 "2010-07-11T21:38:12Z")

</div>

Thanks Stefano. It has been a major help.

Also, thank you to others who’ve responded.

Stefano C. wrote:

> age\_numeric = begin Integer(age)  
> rescue ArgumentError  
> puts “Enter a valid number”  
> exit  
> end  
> #months is already an integer, so there’s no need to call to\_i on it  
> monthsold = age\_numeric \* months
> 
> I hope this helps
> 
> Stefano

---

<div class="post-metadata">

**Author:** ![adambeazley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/5f9b8f/32.png) [@adambeazley](https://www.ruby-forum.com/u/adambeazley)\
**Post date:** [July 11, 2010, 10:53pm UTC](https://www.ruby-forum.com/t/basic-question-how-do-you-check-to-see-if-gets-is-a-number/191393/6 "2010-07-11T22:53:32Z")

</div>

Rick Denatale wrote:

> On Sun, Jul 11, 2010 at 12:34 PM, Adam B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
> wrote:
> 
> > if ( age.to\_f.to\_s == true )
> 
> This will NEVER happen.
> 
> age.to\_f converts the string to a float. If the string isn’t valid it  
> returns 0.0.

I’d use Float(age), which will raise an exception for invalid values.

irb(main):001:0\> Float(“1”)  
=\> 1.0  
irb(main):002:0\> Float(“1.5”)  
=\> 1.5  
irb(main):003:0\> Float("1.5 ")  
=\> 1.5  
irb(main):004:0\> Float(“1.5 z”)  
ArgumentError: invalid value for Float(): “1.5 z”  
from (irb):4:in `Float’  
from (irb):4  
from :0

> Now I’m not sure whether or not you really want to accept an age as a  
> float, or just an integer, but you need to do something else to  
> validate the string.
> 
> One way would be to use a regular expression, e.g. something like
> 
> if age =~ /^d+$/ # for an integer

except that particular regexp allows strings which are not just numbers,  
e.g.

> > age = “foo\n123\nbar”  
> > =\> “foo\n123\nbar”  
> > puts “oops” if age =~ /^\d+$/  
> > oops  
> > =\> nil

Use \A and \z to match start and end of the string.

> or  
> if age =~/^d+(|.\d\*)$/ # for a float

except that particular regexp allows invalid floats (e.g. “1.”) and  
disallows valid ones (e.g. “1.0e5”)

Using regexps to validate data is perfectly reasonable, just be very  
careful that the regexp you write matches exactly what you expect and  
nothing else.

> Or use either Kernel#Integer or Kernel#Float which raise an error if  
> they don’t like the string:
> 
> float\_age = Float(age) rescue nil  
> if float\_age  
> #…

Beware that Integer() handles values which start with zero as octal.

> > “0100”.to\_i  
> > =\> 100  
> > Integer(“0100”)  
> > =\> 64

---

<div class="post-metadata">

**Author:** ![adambeazley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/5f9b8f/32.png) [@adambeazley](https://www.ruby-forum.com/u/adambeazley)\
**Post date:** [July 12, 2010, 1:24am UTC](https://www.ruby-forum.com/t/basic-question-how-do-you-check-to-see-if-gets-is-a-number/191393/7 "2010-07-12T01:24:29Z")

</div>

On Sun, Jul 11, 2010 at 4:53 PM, Brian C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> Use \A and \z to match start and end of the string.

In general you are right, but ignoring my typo leaving out the \ in  
\d, in this case the string came from gets so the multi-line string  
case won’t arise.

–  
Rick DeNatale

Blog: [http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)  
Github: [rubyredrick (Rick DeNatale) · GitHub](http://github.com/rubyredrick)  
Twitter: @RickDeNatale  
WWR: [http://www.workingwithrails.com/person/9021-rick-denatale](http://www.workingwithrails.com/person/9021-rick-denatale)  
LinkedIn: [http://www.linkedin.com/in/rickdenatale](http://www.linkedin.com/in/rickdenatale)

---

<div class="post-metadata">

**Author:** ![adambeazley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/5f9b8f/32.png) [@adambeazley](https://www.ruby-forum.com/u/adambeazley)\
**Post date:** [July 12, 2010, 2:22am UTC](https://www.ruby-forum.com/t/basic-question-how-do-you-check-to-see-if-gets-is-a-number/191393/8 "2010-07-12T02:22:25Z")

</div>

Hi –

On Mon, 12 Jul 2010, Rick DeNatale wrote:

> > =\> nil
> > 
> > Use \A and \z to match start and end of the string.
> 
> In general you are right, but ignoring my typo leaving out the \ in  
> \d, in this case the string came from gets so the multi-line string  
> case won’t arise.

> > $/ = “r”  
> > =\> “r”  
> > str = gets  
> > foo  
> > 123  
> > bar  
> > =\> “foo\n123\nbar”

Yes, yes, I know 🙂

David

–  
David A. Black, Senior Developer, Cyrus Innovation Inc.

The Ruby training with Black/Brown/McAnally  
Compleat Stay tuned for next event announcement!  
Rubyist [http://www.compleatrubyist.com](http://www.compleatrubyist.com)
