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

**URL:** <https://rubytalk.org/t/basic-question-how-do-you-check-to-see-if-gets-is-a-number/59146>\
**Category:** ruby-talk\
**Created:** [11 July 2010 16:34 UTC](https://rubytalk.org/t/basic-question-how-do-you-check-to-see-if-gets-is-a-number/59146 "2010-07-11T16:34:56Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Adam\_Bourg](https://avatars.discourse-cdn.com/v4/letter/a/898d66/32.png) [@Adam\_Bourg](https://rubytalk.org/u/Adam_Bourg)\
**Post date:** [11 July 2010 16:34 UTC](https://rubytalk.org/t/basic-question-how-do-you-check-to-see-if-gets-is-a-number/59146/1 "2010-07-11T16:34:56Z")

</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 Bourg 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 )  
&nbsp;&nbsp;monthsold = age.to\_i \* months.to\_i  
&nbsp;&nbsp;puts 'You are ' + monthsold.to\_s + ' months old'  
else  
&nbsp;&nbsp;puts 'Error, please enter a number!'  
&nbsp;&nbsp;end

Attachments:  
[http://www.ruby-forum.com/attachment/4848/Screen\_shot\_2010-07-11\_at\_10.33.56\_AM.png](http://www.ruby-forum.com/attachment/4848/Screen_shot_2010-07-11_at_10.33.56_AM.png)

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![Stefano\_Crocco](https://avatars.discourse-cdn.com/v4/letter/s/5f9b8f/32.png) [@Stefano\_Crocco](https://rubytalk.org/u/Stefano_Crocco)\
**Post date:** [11 July 2010 17:02 UTC](https://rubytalk.org/t/basic-question-how-do-you-check-to-see-if-gets-is-a-number/59146/2 "2010-07-11T17:02:48Z")

</div>

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  
&nbsp;&nbsp;...  
else  
&nbsp;&nbsp;...  
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  
&nbsp;&nbsp;puts "Enter a valid number"  
&nbsp;&nbsp;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

> **···**
>
> On Sunday 11 July 2010, Adam Bourg wrote:
> 
> > \>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 Bourg 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:** ![Rick\_DeNatale1](https://avatars.discourse-cdn.com/v4/letter/r/bbce88/32.png) [@Rick\_DeNatale1](https://rubytalk.org/u/Rick_DeNatale1)\
**Post date:** [11 July 2010 17:05 UTC](https://rubytalk.org/t/basic-question-how-do-you-check-to-see-if-gets-is-a-number/59146/3 "2010-07-11T17:05:15Z")

</div>

> 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

> **···**
>
> On Sun, Jul 11, 2010 at 12:34 PM, Adam Bourg \<adam.bourg89@gmail.com\> wrote:
> 
> --  
> 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:** ![Doc\_O\_Leary1](https://avatars.discourse-cdn.com/v4/letter/d/ba8739/32.png) [@Doc\_O\_Leary1](https://rubytalk.org/u/Doc_O_Leary1)\
**Post date:** [11 July 2010 17:35 UTC](https://rubytalk.org/t/basic-question-how-do-you-check-to-see-if-gets-is-a-number/59146/4 "2010-07-11T17:35:07Z")

</div>

In article \<c2a8f01abcd51484ec6a1704fda75ebb@ruby-forum.com\>,

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

> **···**
>
> Adam Bourg \<adam.bourg89@gmail.com\> wrote:
> 
> --  
> My personal UDP list: 127.0.0.1, localhost, googlegroups.com, astraweb.com,  
> &nbsp;&nbsp;&nbsp;&nbsp;and probably your server, too.

---

<div class="post-metadata">

**Author:** ![Adam\_Bourg](https://avatars.discourse-cdn.com/v4/letter/a/898d66/32.png) [@Adam\_Bourg](https://rubytalk.org/u/Adam_Bourg)\
**Post date:** [11 July 2010 19:38 UTC](https://rubytalk.org/t/basic-question-how-do-you-check-to-see-if-gets-is-a-number/59146/5 "2010-07-11T19:38:14Z")

</div>

Thanks Stefano. It has been a major help.

Also, thank you to others who've responded.

Stefano Crocco wrote:

> **···**
>
> > age\_numeric = begin Integer(age)  
> > rescue ArgumentError  
> > &nbsp;&nbsp;puts "Enter a valid number"  
> > &nbsp;&nbsp;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
> 
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Brian\_Candler](https://avatars.discourse-cdn.com/v4/letter/b/5f9b8f/32.png) [@Brian\_Candler](https://rubytalk.org/u/Brian_Candler)\
**Post date:** [11 July 2010 20:53 UTC](https://rubytalk.org/t/basic-question-how-do-you-check-to-see-if-gets-is-a-number/59146/6 "2010-07-11T20:53:34Z")

</div>

Rick Denatale 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"  
&nbsp;&nbsp;from (irb):4:in `Float'  
&nbsp;&nbsp;from (irb):4

> 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

> **···**
>
> > On Sun, Jul 11, 2010 at 12:34 PM, Adam Bourg \<adam.bourg89@gmail.com\> \> wrote:
> 
> &nbsp;&nbsp;from :0  
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Rick\_DeNatale1](https://avatars.discourse-cdn.com/v4/letter/r/bbce88/32.png) [@Rick\_DeNatale1](https://rubytalk.org/u/Rick_DeNatale1)\
**Post date:** [11 July 2010 23:22 UTC](https://rubytalk.org/t/basic-question-how-do-you-check-to-see-if-gets-is-a-number/59146/7 "2010-07-11T23:22:02Z")

</div>

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.

> **···**
>
> On Sun, Jul 11, 2010 at 4:53 PM, Brian Candler \<b.candler@pobox.com\> wrote:
> 
> > > 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.
> 
> --  
> Rick DeNatale
> 
> Blog: [http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)  
> Github: [http://github.com/rubyredrick](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:** ![David\_A\_Black1](https://avatars.discourse-cdn.com/v4/letter/d/bcef8e/32.png) [@David\_A\_Black1](https://rubytalk.org/u/David_A_Black1)\
**Post date:** [12 July 2010 00:21 UTC](https://rubytalk.org/t/basic-question-how-do-you-check-to-see-if-gets-is-a-number/59146/8 "2010-07-12T00:21:53Z")

</div>

Hi --

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

&nbsp;&nbsp;&nbsp;\>\> $/ = "r"  
&nbsp;&nbsp;&nbsp;=\> "r"  
&nbsp;&nbsp;&nbsp;\>\> str = gets  
&nbsp;&nbsp;&nbsp;foo  
&nbsp;&nbsp;&nbsp;123  
&nbsp;&nbsp;&nbsp;bar  
&nbsp;&nbsp;&nbsp;=\> "foo\n123\nbar"

Yes, yes, I know 🙂

David

> **···**
>
> On Mon, 12 Jul 2010, Rick DeNatale wrote:
> 
> > On Sun, Jul 11, 2010 at 4:53 PM, Brian Candler \<b.candler@pobox.com\> wrote:
> 
> --  
> David A. Black, Senior Developer, Cyrus Innovation Inc.
> 
> &nbsp;&nbsp;&nbsp;The Ruby training with Black/Brown/McAnally  
> &nbsp;&nbsp;&nbsp;Compleat Stay tuned for next event announcement!  
> &nbsp;&nbsp;&nbsp;Rubyist [http://www.compleatrubyist.com](http://www.compleatrubyist.com)
