At 01:19 AM 10/19/01 +0100, Ian Phillipps wrote:
>On Thu, 18 Oct 2001 at 18:33:53 -0400, Selector, Lev Y wrote:
> > Wow! This is really elegant !!
>
> > -----Original Message-----
> > From: Josh Goldberg [mailto:[EMAIL PROTECTED]]
>
> > sub isNumber {
> >         !/\d/ ? 0 : $_ == 0 ? 1 : $_ * 1
> > }
>
>Possibly elegant, but definitely not correct.
>
>Anything non-numeric, but with digits in, will generate an ugly warning
>and incorrectly return "1". Try 'foo0' and you'll see what I mean.
>You did try the -w switch, didn't you?
>
>I prefer Lev's original, and offer this as an improvement:
>
>sub isNumber($){
>     $_[0] =~ /^(?=[-+.]*\d)[-+]?\d*\.?\d*(?:e[-+ ]?\d+)?$/i
>}
>
>The initial zero-width assertion is to prevent ".e5" from being a
>number, while permitting "123.".
>
>The space after the "e" is in deference to FORTRAN, which writes numbers
>like "1.23E 01". But that's a matter of taste.
>
>I feel sure this is a FAQ...

Amazingly, so does "perldoc -q number":

        How do I determine whether a scalar is a
        number/whole/integer/float?

        Assuming that you don't care about IEEE notations like
        "NaN" or "Infinity", you probably just want to use a
        regular expression.

           if (/\D/)            { print "has nondigits\n" }
           if (/^\d+$/)         { print "is a whole number\n" }
           if (/^-?\d+$/)       { print "is an integer\n" }
           if (/^[+-]?\d+$/)    { print "is a +/- integer\n" }
           if (/^-?\d+\.?\d*$/) { print "is a real number\n" }
           if (/^-?(?:\d+(?:\.\d*)?|\.\d+)$/) { print "is a decimal number" }
           if (/^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/)
                                { print "a C float" }

        If you're on a POSIX system, Perl's supports the
        "POSIX::strtod" function.  Its semantics are somewhat
        cumbersome, so here's a "getnum" wrapper function for more
        convenient access.  This function takes a string and
        returns the number it found, or "undef" for input that
        isn't a C float.  The "is_numeric" function is a front end
        to "getnum" if you just want to say, ``Is this a float?''

            sub getnum {
                use POSIX qw(strtod);
                my $str = shift;
                $str =~ s/^\s+//;
                $str =~ s/\s+$//;
                $! = 0;
                my($num, $unparsed) = strtod($str);
                if (($str eq '') || ($unparsed != 0) || $!) {
                    return undef;
                } else {
                    return $num;
                }
            }

            sub is_numeric { defined getnum($_[0]) }

        Or you could check out the String::Scanf module on CPAN
        instead.  The POSIX module (part of the standard Perl
        distribution) provides the "strtod" and "strtol" for
        converting strings to double and longs, respectively.


--
Peter Scott
Pacific Systems Design Technologies
http://www.perldebugged.com

Reply via email to