Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

How to identify a number datatype in a string?

by BBQ (Curate)
on Jan 15, 2000 at 03:35 UTC ( [id://2114]=perlquestion: print w/replies, xml ) Need Help??

BBQ has asked for the wisdom of the Perl Monks concerning the following question: (numbers)

We all know that perl is good for it's so called lack of datatype declarations (and a bunch of other things). But what if you WANT to know if your string is an integer? Furthermore, what if your integer has already been formatted? This is the code that I came up with, but I feel it could be greatly improoved. Suggestions are > welcome!

Originally posted as a Categorized Question.

  • Comment on How to identify a number datatype in a string?

Replies are listed 'Best First'.
Re: How to identify a number datatype in a string?
by chromatic (Archbishop) on Apr 02, 2000 at 06:18 UTC
    The Perl Cookbook suggests that the following regex will match C floats: $var =~ /^([+-]?)(?=\d|\.\d)\d*(\.\d)?([Ee]([+-]?\d+))?$/; That may be overkill for your purposes, though.

    Update: (Tue Jan 8 16:03:52 UTC 2002) Removed spurious left paren (thanks, Petruchio).

Re: How to identify a number datatype in a string?
by vroom (His Eminence) on Jan 18, 2000 at 22:47 UTC
    #!/usr/bin/perl # check for numbers with punctuation use Strict; # examples for "common-written" numbers foreach my $var ( # should be false '','foo 30','.20','20.',',20','20,', # should be numbers 0,100,'100.23','1,100.23' ) { if (IsANumber($var)) { print "True: $var\n"; } else { print "False: $var\n"; } } sub IsANumber { my $var = $_[0]; if ( # contains digits,commas and 1 period ($var =~ /(^[0-9]{1,}?$)|(\,*?)|(\.{1})/) && # does not contain alpha's, more than 1 period # commas or periods at the beggining and ends of # each line !($var =~ /([a-zA-Z])|(^[\.\,]|[\.\,]$)/) && # is not null ($var ne '') ) { return(1) } else { return(0) } }
Re: How to identify a number datatype in a string?
by astaines (Curate) on Aug 12, 2001 at 04:31 UTC

    USe an eval, it's correct (by definition) and avoids possible errors

    my @numbers = ( '1', '2', '10', '1.2', '1e2', '1.02e2', '1.02e-2', 'e-2', 'er', 'et', '0er' ); foreach my $number (@numbers) { my $test = $number; eval { $test +=0; }; if ( $@ ) { print "$number isn't a number \n"; } }

    {QA Editors note: This solution doesn't work as described. See Re: Answer: How to identify a number datatype in a string? for more explanation.}

    Edited by davido: Repaired <code> tags, reformatted code. Added editorial note to clarify why this example is broken.

    --

    Anthony Staines

      Uh, this doesn't seem to work at all...
      laptop:~> perl -T my @numbers = ('1','2','10','1.2','1e2','1.02e2', '1.02e-2','e-2','er','et','0er', 'total and complete non number stuff'); foreach my $number (@numbers) { my $test = $number; eval { $test +=0; }; if ( $@ ) { print "$number isn't a number \n"; } } laptop:~>
      Here are my particulars...

        Add the following after if(@){}, and you will see...

        else { print "number: ", $test , "\n"; }

        ...Apparently, $test is assigned zero (perl 5.8.0) when $number is not a number. Ergo, no errors in eval, no print.

Re: How to identify a number datatype in a string?
by rbi (Monk) on Apr 13, 2001 at 18:22 UTC
    I think that both the Cookbook and vroom miss some valid numbers.
    Here's my proposed checker. HOpe I don't get wrong ones, instead :)
    Roberto
    #!/usr/bin/perl # check for numbers with punctuation use strict; # examples for "common-written" numbers foreach my $var ( '','foo 30','.20','20.',',20','20,','1.3E2', '2..3','++3','2.3.', ,'..3', 0,100,'100.23','1,100.23','-3E-2' ) { print "String: $var\n"; if (IsANumber($var)) { print "vroom says True, "; } else { print "vroom says False, "; } if (IsANumberCookbook($var)) { print "Cookbook says True, "; } else { print "Cookbook says False, "; } if (IsANumberMine($var)) { my $out = $var * $var; print "I say True and square is $out\n\n"; } else { print "I say False\n\n"; } } sub IsANumber { # vroom version my $var = $_[0]; if ( # contains digits,commas and 1 period ($var =~ /(^[0-9]{1,}?$)|(\,*?)|(\.{1})/) && # does not contain alpha's, more than 1 period # commas or periods at the beggining and ends of # each line !($var =~ /([a-zA-Z])|(^[\.\,]|[\.\,]$)/) && # is not null ($var ne '') ) { return(1) } else { return(0) } } sub IsANumberCookbook { # Perl Cookbook version my $var = $_[0]; if ( $var =~ /^([+-]?)(?=\d|\.\d)\d*(\.\d)?([Ee]([+-]?\d+) +)?$/ ) { return(1) } else { return(0) } } sub IsANumberMine { # my version my $var = $_[0]; if ( $var =~ /^([+-]?)(\d+\.|\.\d+|\d+)\d*([Ee]([+-]?\d+)) +?$/ ) { return(1) } else { return(0) } }
Re: How to identify a number datatype in a string?
by jdhedden (Deacon) on Sep 23, 2005 at 17:52 UTC
    Scalar::Util has a function looks_like_number() for just this purpose. It is included in Perl 5.8, or you can get it from CPAN.

    You can use looks_like_number() in conjunction with int() to tell what type of number you have.

    #!/usr/bin/perl use strict; use warnings; use Scalar::Util qw(looks_like_number); my $x = $ARGV[0]; if (looks_like_number($x)) { if (int($x) == $x) { print("$x is an integer\n"); } else { print("$x is numeric\n"); } } else { print("Your input was not numeric\n"); }
Re: How to identify a number datatype in a string?
by Anonymous Monk on May 06, 2002 at 06:12 UTC
    Identify String or number: Ben Young;
    I tried this and it only fails on $x = '0.0', but not $x = 0.0

    if (($m == 0) && !($m eq '0')) {print "string\n";} else {print "number +\n";}

    It works since PERL treats strings as 0 in numeric tests. (It also pulls numbers out of strings if the numbers come first)

    Edited by davido: Added code tags. Reformatted.

Re: How to identify a number datatype in a string?
by Anonymous Monk on Jul 31, 2002 at 15:37 UTC
    The first regex given on this page to identify a number fails with:
    "1.233e+23", "1.233"

    but succeeds with:
    "1.2e+233"

    Appears to be some sort of problem with multiple digits after a decimal point.

    The regex is:

    /^([+-]?)(?=\d|\.\d)\d*(\.\d)?([Ee]([+-]?\d+))?$/

    A slightly modified version which does work for the given cases:

    /^([+-]?)(?=\d|\.\d+)\d*(\.\d+)?([Ee]([+-]?\d+))?$/

    The only difference is the extra plus's after each \.

    Edited by davido: Added <code> tags.

Re: How to identify a number datatype in a string?
by Bilbo (Pilgrim) on May 09, 2003 at 13:08 UTC

    The mehod suggested by astaines works but the script he gives does not because perl only warns about adding to non-numeric variables, so this is not caught by the eval. It is therefore necessary to make warnings fatal within the eval block:

    sub is_number { my $test = shift; eval { local $SIG{__WARN__} = sub {die $_[0]}; $test += 0; }; if ($@) {return 0;} else {return 1;} }

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://2114]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (3)
As of 2024-04-26 00:09 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found