Re: numeric comparison
by gjb (Vicar) on Jul 15, 2003 at 09:12 UTC
|
Have a look at Regexp::Common, it has patterns for real numbers (and many other common things).
Just my 2 cents, -gjb-
| [reply] |
Re: numeric comparison
by Abigail-II (Bishop) on Jul 15, 2003 at 09:24 UTC
|
If it's ok if 'xxx' compares as 0, you
could also turn the appropriate warning off (locally).
Something like:
if (do {no warnings 'numeric'; $foo < 4.556}) {
...
}
Abigail | [reply] [d/l] |
Re: numeric comparison
by dbp (Pilgrim) on Jul 15, 2003 at 10:08 UTC
|
warn "has nondigits" if /\D/;
warn "not a natural number" unless /^\d+$/; # rejects -3
warn "not an integer" unless /^-?\d+$/; # rejects +3
warn "not an integer" unless /^[+-]?\d+$/;
warn "not a decimal number" unless /^-?\d+\.?\d*$/; # rejects .2
warn "not a decimal number" unless /^-?(?:\d+(?:\.\d*)?|\.\d+)$/;
warn "not a C float"
unless /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/;
| [reply] [d/l] |
Re: numeric comparison
by BrowserUk (Patriarch) on Jul 15, 2003 at 10:34 UTC
|
sub is_numeric{ use POSIX (); !(POSIX::strtod($_[0]))[1]; }
However, if you download and build the latest cpan version of Scalar::Util (the version that comes with 5.8.0 doesn't have it), it provides access to perl's internal looks_like_number(); which ought to be quicker than either strtod() or a regex.
NOTE: If your not set up to build XS modules, then List::Util and Scalar::Util will silently fall back to using Perl implementations of the functions they provide. In the case of Looks_like_number(), this is a regex.
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
| [reply] [d/l] [select] |
|
use Scalar::Util 'looks_like_number';
my @candidates = qw/ 1 1.1 1,1 0E0 0e0 0377 100_000 0xdeadbeef/;
print $_,
looks_like_number($_)? ' is' : ' is not',
' a number.',
$/
for @candidates;
__END__
1 is a number.
1.1 is a number.
1,1 is not a number.
0E0 is a number.
0e0 is a number.
0377 is a number.
100_000 is not a number.
0xdeadbeef not is a number.
After Compline, Zaxo | [reply] [d/l] |
|
print 3 + '0xdeadbeef';
Argument "0xdeadbeef" isn't numeric in addition (+) at ...
3
print 3 + 0xdeadbeef;
3735928562
print 3+ '100_000';
Argument "100_000" isn't numeric in addition (+) at ...
103
print 3+ 100_000;
100003
Which I guess means that the code used to extract a number from a string at runtime is a different routine to that used for parsing numeric constants at compile time. Which is slightly disappointing, but is probably done that way for very good reasons.
I just wish that the version of Scalar-List-Utils on the AS 5.8 list included the compiled XS code. That is that possible isn't it?
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
| [reply] [d/l] |
Re: numeric comparison
by derby (Abbot) on Jul 15, 2003 at 12:12 UTC
|
dbp gave you the faq supported answer and it can be found in
perlfaq4 under "How do I determine whether a scalar is a number/whole/integer/float?". Then check the Floating-point Arithmetic section of perlop as to why your comparison
of a float is going to lead you down a subtle path of bugs.
-derby | [reply] |
Re: numeric comparison
by Tanalis (Curate) on Jul 15, 2003 at 09:12 UTC
|
Why not use a regexp? Something like ...
unless ($foo =~ /^\-?\d*\.?\d*$/) {
# do something
}
should do the trick.
Hope that helps.
-- Foxcub
#include www.liquidfusion.org.uk
Update: Doh, updated regexp to something that stands a chance in hell of actually working .. (thanks, antirice) | [reply] [d/l] |
|
| [reply] |
Re: numeric comparison
by antirice (Priest) on Jul 15, 2003 at 09:15 UTC
|
$word =~ /^-?(\d*)\.?(\d*)$/ && (length($1) || length($2));
What's with the length checks? ".807" and "30." are valid numbers whereas "." is not. Hope this helps.
antirice The first rule of Perl club is - use Perl The ith rule of Perl club is - follow rule i - 1 for i > 1 | [reply] [d/l] |
Re: numeric comparison
by edan (Curate) on Jul 15, 2003 at 10:10 UTC
|
I recently wrote a regex to match a floating-point number, including (optional) scientific notatation. This looks like a good chance to get some critique, as well as (possibly) help you. I think it's a bit more complete than the regexen I've seen so far in this post, though I'm sure it's far from perfect.
/^[+-]?(?=\.?\d)\d*(\.\d*)?([Ee][+-]?\d+)?$/
HTH
Update: Well, at least my regex is validated by the Perl Cookbook, as shown in dbp's post. Though I'm curious to know why they used (?=\d|\.\d) instead of (?=\.?\d), when it seems to me the latter is more concise... anyone know of a good reason?
-- 3dan | [reply] [d/l] |