The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
<CENTER>
<TITLE>Is it a Number?</TITLE>
<H1><I>Is it a Number?</i></h1>
</CENTER>

In innumerable postings and email the following question eternally arises:

<BLOCKQUOTE><i>
How do I test a string to see if it's a number?
</i></BLOCKQUOTE>

I hate this question.

<BLOCKQUOTE><I>
I'm sure there's an obvious answer to this, 
</I></BLOCKQUOTE>

Why yes, there is.  I generally like this way:

<XMP>
    if ($n == 0) { warn "icky number" } 
</XMP>

<BLOCKQUOTE><I>
but I haven't yet found or
figured it out.  Thanks...
</I></BLOCKQUOTE>

Why do you want to see whether it's a number?  Perl is happy
to use strings and numbers interchangeably.  People make way too 
much trouble of this.  Normally, all you want to do is
<PRE>
    $answer += 0;
</PRE>
To perform this conversion, Perl merely  calls your native C librarys's <I>atof(3)</I> function.
Many important benefits come from this approach, which if you try to roll it yourself, 
you'll probably miss.  Here are some of them:
<OL>
    <LI>Your current <B><font size=-1>LC_NUMERIC</font></B> locale setting is used and respected.  
	This means that the user's local radix will be respected.  For example,
	if you're in a country where the USA's notion of comma and period 
	are switched, the right thing will still happen.  
    <LI>Exponent overflow and underflow produce the  results  
	    specified  by  the  <font size=-1>IEEE</font>  Standard.  
    <LI>The special <font size=-1>IEEE</font> notions of 
	    <I>Infinity</I> and 
	    <I>NaN</I> (not a number) will be properly honored:
<PRE><CODE>
  $n = 'NaN';
  print 2 * $n;
<B>NaN</B>
  print 10 * $n
<B>NaN</B>
  print 1 + NaN
<B>NaN</B>
  $i = 'Infinity' 
  print 1 + $i
<B>Infinity</B>
  print $i * $i
<B>Infinity</B>
  print $i - $i
<B>NaN</B>
  print 'Infinity' &lt; 0
<B>0</B>
  print 'Infinity' &gt; 0
<B>1</B>
</CODE></PRE></OL>

You may also notice that <TT>NaN</TT> is neither 
<TT>==</TT>
nor
<TT>!=</TT> 0, which is probably what you want.
If you disagree with the way your vendor has implemented <I>atof(3)</I>,
then complain to them, but you'd better be up on your standards docs first.
If you don't like that 
<I>atof(3)</I> tolerates trailing non-numerics, just cope.

<P>
Assuming you don't care about whether something's zero or has trailing garbage, some
slightly simplistic solutions certainly suggest themselves:

<XMP>
    do { 
	print "Number, please: ";
	$answer = <STDIN>;
	print "Bad number\n" if $answer == 0;
    } until $answer;
</XMP>

If you do care about getting 0's, then do this:

<XMP>
    do { 
	print "Number, please: ";
	$answer = <STDIN>;
	if ($answer == 0 && $answer ne '0') {
	    print "Bad number\n";
	}
    } until $answer;
</XMP>

A related  approach is to see whether the lexical and numeric
representations are the same.  This solution is often
by those who don't like trailing non-digits in their numbers:

<XMP>
    do { 
	print "Number, please: ";
	$answer = <STDIN>;
	if ($answer+0 ne $answer) {
	    print "Bad number\n";
	}
    } until $answer;
</XMP>

<P>

If you find yourself unduly annoyed from being chidden  about improper numeric
conversions, as I'm sure I'm about to be, just do something like this:

<XMP>
    do { 
	print "Number, please: ";
	$answer = <STDIN>;
	local $^W = 0;
	if ($answer == 0 && $answer ne '0') {
	    print "Bad number\n";
	}
    } until $answer;
</XMP>

If you want to wrap it in a function, do this:

<XMP>
    sub bogus_number {
	my $potential_number = shift;
	local $^W = 0;
	my $bogosity = $potential_number == 0 
		    && $potential_number ne '';
	return $bogosity;
    } 
</XMP>

Hm... one of these days we're going to have deal with this problem of
maybe getting <B><font size=-1>EOF</font></B>.  Remember you can't actually test for <I>eof()</I> explicitly,
or you'll hose the interactive user.

<XMP>
    do { 
	print "Number, please: ";
	exit unless defined ($answer = <STDIN>);
	if (bogus_number($answer)) { 
	    print "Bad number\n";
	    $answer = 0;
	}
    } until $answer;
</XMP>

You could even be cruel and clobber their input:

<XMP>
    sub bogus_number {
	local $^W = 0;
	if ($_[0] == 0 && $_[0] ne '') {
	    $_[0] = ''; # squish my caller!
	    return 1;
	} 
	return 0;
    } 

    do { 
	print "Number, please: ";
	$answer = <STDIN>;
	print "Bad number\n" if bogus_number($answer);
    } until $answer;
</XMP>

Or write it the other way:
 
<XMP>
    do {
	print "Number, please: ";
	$answer = <STDIN>;
    } until nifty_number($answer);

    sub nifty_number {
	my $potential_number = shift;
	local $^W = 0;
	my $bogosity = $potential_number == 0 
		    && $potential_number ne '';
	return !$bogosity;
    } 
</XMP>

Someone is going to ask the question ``Can't I use a regular expression do
this?''  Why, yes, Virginia, you may, and don't say can. :-)  Actually, regular
expressions 
are the general way one verifies input in Perl.  Here are some
simple-minded schemes for detecting such things:

<XMP>
    sub is_whole_number { $_[0] =~ /^\d+$/            }
    sub is_integer      { $_[0] =~ /^[+-]?\d+$/       }
    sub is_float        { $_[0] =~ /^[+-]?\d+\.?\d*$/ }
    </XMP>

For a more proper solution, 
chew on this
output from an old paper-tape processing machine from Mark Biggar:

<XMP>
    sub nifty_number { 
	$_[0] =~ /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/;
    }
</XMP>

or written out more legibly:

<XMP>
    sub nifty_number {
        $_[0] =~ m{   # YANETUT
                    ^ ( [+-]? )
                      (?= \d 
                        | \.\d 
                      )
                      \d*
                      ( \. \d* ) ?
                      (   [Ee] ( [+-]? \d+ ) ) ?
                    $
	}x
    }
</XMP>

Nearly all of these solutions suffer from problems that the simple
<CODE>
    $num += 0;
</CODE>
has no problems with.