Joe Discenza wrote:
> Chris Wagner wrote, on Thu 6/30/2005 14:41
>
> : At 12:16 PM 6/30/05 -0500, Joe Discenza wrote:
> : >I bet you're right that "eval($var) eq $var + 0" works; have you
> : >benchmarked it against all the other (regex, e.g.) methods presented?
> :
> : I haven't benchmarked it but I can garuntee that it's faster than a regex.
> : Anything's faster than that. ;) This should cover everything:
>
> Thanks for playing. I compared your function with a regex I whipped up
> (/^[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?$/, which gave the same
> results, except for distinguishing "pure" numbers, on your dataset):
>
> Benchmark: timing 100000 iterations of chris, regex...
> chris: 12 wallclock secs (11.86 usr + 0.00 sys = 11.86 CPU) @
> 8432.41/s (n=100000)
> regex: 2 wallclock secs ( 1.56 usr + 0.00 sys = 1.56 CPU) @
> 63979.53/s (n=100000)
>
> Regex is pretty fast. Eval is usually pretty slow.
1) I don't consider Chris's solution to be a legit solution until it
doesn't issue any warnings or error messages.
2) I got these numbers from my test (strict/warnings turned off) :
Rate RE STRTOD IF LLN
RE 7530/s -- -72% -75% -75%
STRTOD 26948/s 258% -- -10% -11%
IF 29782/s 295% 11% -- -2%
LLN 30274/s 302% 12% 2% --
looks_like_number seems to be the winner.
I used the same two lines of code in each sub to clean up
the input:
$var =~ s/^\s+//; $var =~ s/\s+$//;
return 0 if not defined $var or $var eq '';
use strict;
use warnings;
use Scalar::Util qw(looks_like_number);
use POSIX qw(strtod);
use Benchmark qw(timethese cmpthese);
# test output of subs before benchmarking
foreach my $sub (\&sub1, \&sub2, \&sub3, \&sub4) {
foreach ("1e7", 0, 5, "6", "0.00", -4, "abc", "f4fc", '+.1', undef) {
my $val = defined $_ ? $_ : 'undef';
my $ret = &$sub ($_);
print $ret ? "sub1 ($ret): '$val' is a number\n" :
"sub1 ($ret): '$val' is not a number\n";
$ret = &$sub ($_);
print $ret ? "sub2 ($ret): '$val' is a number\n" :
"sub2 ($ret): '$val' is not a number\n";
$ret = &$sub ($_);
print $ret ? "sub3 ($ret): '$val' is a number\n" :
"sub3 ($ret): '$val' is not a number\n";
$ret = &$sub ($_);
print $ret ? "sub4 ($ret): '$val' is a number\n" :
"sub4 ($ret): '$val' is not a number\n";
}
}
no warnings; # needed for Chris solution
no strict; # needed for Chris solution
my $count = 1000000;
cmpthese ($count, {
RE => 'main (\&sub1)',
IF => 'main (\&sub2)',
STRTOD => 'main (\&sub3)',
LLN => 'main (\&sub4)',
});
sub main {
my $cref = shift;
foreach ("1e7", 0, 5, "6", "0.00", -4, "abc", "f4fc", '+.1', undef) {
&$cref ($_);
}
}
sub sub1 {
my $var = shift;
$var =~ s/^\s+//; $var =~ s/\s+$//;
return 0 if not defined $var or $var eq '';
if ($var eq $var + 0) {
return 1;
} elsif (eval $var eq $var + 0) {
return 2;
}
return 0;
}
sub sub2 {
my $var = shift;
$var =~ s/^\s+//; $var =~ s/\s+$//;
return 0 if not defined $var or $var eq '';
return 1 if $var =~ /^[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?$/;
return 0;
}
sub sub3 {
my $var = shift;
$var =~ s/^\s+//; $var =~ s/\s+$//;
return 0 if not defined $var or $var eq '';
$! = 0;
my ($num, $unparsed) = strtod ($var);
return 0 if $unparsed or $!;
return 1;
}
sub sub4 {
my $var = shift;
$var =~ s/^\s+//; $var =~ s/\s+$//;
return 0 if not defined $var or $var eq '';
# return looks_like_number ($var);
# code stripped from LLN:
return 1 if (/^[+-]?\d+$/); # is a +/- integer
return 1 if (/^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/); # a C float
return 1 if ($] >= 5.008 and /^(Inf(inity)?|NaN)$/i) or
($] >= 5.006001 and /^Inf$/i);
}
__END__
--
,-/- __ _ _ $Bill Luebkert Mailto:[EMAIL PROTECTED]
(_/ / ) // // DBE Collectibles Mailto:[EMAIL PROTECTED]
/ ) /--< o // // Castle of Medieval Myth & Magic http://www.todbe.com/
-/-' /___/_<_</_</_ http://dbecoll.tripod.com/ (My Perl/Lakers stuff)
_______________________________________________
Perl-Win32-Users mailing list
[email protected]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs