Dear Monks,

I found on the perlfaq4 the following code:

use 5.010; given( $number ) { when( /\D/ ) { say "\thas nondigits"; continue } when( /^\d+\z/ ) { say "\tis a whole number"; continue } when( /^-?\d+\z/ ) { say "\tis an integer"; continue } when( /^[+-]?\d+\z/ ) { say "\tis a +/- integer"; continue } when( /^-?(?:\d+\.?|\.\d)\d*\z/ ) { say "\tis a real number"; continue } when( /^[+-]?(?=\.?\d)\d*\.?\d*(?:e[+-]?\d+)?\z/i) { say "\tis a C float" } }

I am trying to find a way to determine the element from the array if it is an integer, decimal or float. But I am guessing that I am missing something.

I have modified the code for testing purposes:

#!/usr/bin/perl use strict; use warnings; my @numbers = (1, -1, 123.1, 0.1); foreach my $number (@numbers) { if ($number =~ /\D/ ) { print "The $number has nondigits\n"; } elsif ($number =~ /^\d+\z/ ) { print "The $number is a whole number\n"; } elsif ($number =~ /^-?\d+\z/ ) { print "The $number is an integer\n"; } elsif ($number =~ /^[+-]?\d+\z/ ) { print "The $number is a +/- integer\n"; } elsif ($number =~ /^-?(?:\d+\.?|\.\d)\d*\z/ ) { print "The $number is a real number\n"; } elsif ($number =~ /^[+-]?(?=\.?\d)\d*\.?\d*(?:e[+-]?\d+)?\z/i ) { print "The $number is a C float\n"; } }

But I am getting, not the expected output:

The 1 is a whole number The -1 has nondigits The 123.1 has nondigits The 0.1 has nondigits

I would expect something like:

The 1 is a +/- integer The -1 is a +/- integer The 123.1 is a C float The 0.1 is a C float

Update: I was playing around to see if by modifying the numbers to string in the array will affect the output. I modified the my @numbers = (1, 1.0, 123.1, 0.1); to my @numbers = qw(1, 1.0, 123.1, 0.1);. That was the only modification that I applied and the output of the script changes only the first line The 1 is a whole number to The 1, has nondigits.

At this point I am sure that I am doing something completely wrong but I can not figure out what is it. Can someone help understand why I can not get the expected output?

Update 2: I also found from Is it a Number?.

my @numbers = ("1", "-1", "123.1", "0.1"); foreach my $number (@numbers) { my $integer = is_integer($number); print "$number is Integer\n" if ($integer); my $float = is_float($number); print "$number is Float\n" if ($float); } sub is_integer { $_[0] =~ /^[+-]?\d+$/ } sub is_float { $_[0] =~ /^[+-]?\d+\.?\d*$/ } __END__ Output: 1 is Integer 1 is Float -1 is Integer -1 is Float 123.1 is Float 0.1 is Float

Update 3: As shmem pointed out, what I was afraid of, that regex compare against strings. So I guess the array to compare against should be modified to my @numbers = qw(1  1.0  123.1  0.1); as Laurent_R has pointed out. So the code should be like this:

#!/usr/bin/perl use strict; use warnings; my @numbers = qw(1 -1 123.1 0.1 Characters); foreach my $number (@numbers) { if ($number =~ /^[+-]?\d+\z/ ) { print "The $number is a +/- integer\n"; } elsif ($number =~ /^[+-]?(?=\.?\d)\d*\.?\d*(?:e[+-]?\d+)?\z/i ) { print "The $number is a C float\n"; } elsif ($number =~ /\D/ ) { print "The $number has nondigits\n"; } } __END__ The 1 is a +/- integer The -1 is a +/- integer The 123.1 is a C float The 0.1 is a C float The Characters has nondigits

Which starts to make more sense.

Update 4: An alternative and possibly better solution would be to use Switch. It will give us the same output.

#!/usr/bin/perl use strict; use warnings; my @numbers = qw(1 -1 123.1 0.1 Characters); foreach my $number (@numbers) { checkInputStringWithSwitchConditions($number); } sub checkInputStringWithSwitchConditions { use Switch; switch ($_[0]) { case /^[+-]?\d+\z/ { print "The $_[0] is a + +/- integer\n" } case /^[+-]?(?=\.?\d)\d*\.?\d*(?:e[+-]?\d+)?\z/i { print "The $_[0 +] is a C float\n" } case /\D/ { print "The $_[0 +] has nondigits\n" } else { print "Non of the c +ases where True\n" } } } __END__ The 1 is a +/- integer The -1 is a +/- integer The 123.1 is a C float The 0.1 is a C float The Characters has nondigits

Update 5: By comparing the two methods together by using Benchmark, we can see that the Switch method is a better and faster method to use.

#!/usr/bin/perl use strict; use warnings; use Benchmark qw( timethese cmpthese ) ; my @numbers = qw(1 -1 123.1 0.1 Characters); my $swithRefLoop = 'foreach my $number (@numbers) { checkInputStringWithSwitchConditions($number); }'; my $ifAndElsIfRefLoop = 'foreach my $number (@numbers) { checkInputStringWithIfAndElseConditions($number); }'; my $Benchmark = timethese( -10, { IfAndElsIfLoop => $ifAndElsIfRefLoop, SwitchLoop => $swithRefLoop, } ); cmpthese $Benchmark; sub checkInputStringWithSwitchConditions { use Switch; switch ($_[0]) { case /^[+-]?\d+\z/ { print "The $_[0] is a + +/- integer\n" } case /^[+-]?(?=\.?\d)\d*\.?\d*(?:e[+-]?\d+)?\z/i { print "The $_[0 +] is a C float\n" } case /\D/ { print "The $_[0 +] has nondigits\n" } else { print "Non of the c +ases where True\n" } } } sub checkInputStringWithIfAndElseConditions { if ( $_[0] =~ /^[+-]?\d+\z/ ) { print "The $_[0] is a +/- integer\n"; } elsif ( $_[0] =~ /^[+-]?(?=\.?\d)\d*\.?\d*(?:e[+-]?\d+)?\z/i ) { print "The $_[0] is a C float\n"; } elsif ( $_[0] =~ /\D/ ) { print "The $_[0] has nondigits\n"; } } __END__ Benchmark: running IfAndElsIfLoop, SwitchLoop for at least 10 CPU seco +nds... IfAndElsIfLoop: 11 wallclock secs (10.04 usr + -0.00 sys = 10.04 CPU) +@ 4954765.54/s (n=49745846) SwitchLoop: 9 wallclock secs (10.04 usr + 0.00 sys = 10.04 CPU) @ 56 +91789.84/s (n=57145570) Rate IfAndElsIfLoop SwitchLoop IfAndElsIfLoop 4954766/s -- -13% SwitchLoop 5691790/s 15% --

Thank you all for your time and effort reading and replying to my question.

Seeking for Perl wisdom...on the process of learning...not there...yet!

In reply to [SOLVED] How do I determine with a regular expression whether a scalar is a number/whole/integer/float? by thanos1983

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.