Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid


by tlm (Prior)
on Apr 11, 2007 at 20:49 UTC ( #609478=snippet: print w/replies, xml ) Need Help??

A simple way to test for numeric values. It basically asks perl whether it thinks the argument is numeric, by testing whether the argument is "numerically equal" to itself, and trapping any errors.

Update: Dang! I guess one could add !ref($x) && to the last line, but the joy is gone...

Update 2: Thanks Fletch; Scalar::Util::looks_like_number is the way to go.

sub is_numeric {
  use warnings FATAL => qw( numeric uninitialized );
  local $@;
  my $x = shift;
  return eval { $x == $x };
Replies are listed 'Best First'.
Re: is_numeric
by Fletch (Chancellor) on Apr 11, 2007 at 21:22 UTC

    Scalar::Util provides access to the underlying Perl API looks_like_number routine which Perl itself uses internally.

      Scalar::Util provides access to the underlying Perl API looks_like_number routine which Perl itself uses internally

      Perl will evaluate the string (eg) '5621hello' in numeric context as 5621 ... yet looks_like_number() will tell you that the string '5621hello' does not look like a number. That has always struck me as an anomaly .... I tend to think that a a string that "does not look like a number" should evaluate to zero in numeric context, but that (obviously) doesn't always happen.
      use warnings; no warnings 'numeric'; use Scalar::Util; $string = '12.3hello'; print Scalar::Util::looks_like_number($string), "\n"; $string *= 2; print $string, "\n"; __END__ Outputs: 0 24.6
      I don't think this is a big deal, btw - it's just that it doesn't DWIM (for me, anyway).

      Update: I meant to add that this might even have some siginificance for the op - because we can't assume anything about the numeric value of a variable, based on the fact that Scalar::Util says it doesn't look like a number.

        But you've turned off the warning telling you that it doesn't looks_like_number. If you don't have warnings on, Perl assumes you know what you're doing and tries to do what you've asked it to with the (crummy) numberish data you've given it. If you have enabled warnings, it lets you know about it's misgivings but still goes ahead and does what you've asked.

        I think the expectation mismatch is because Perl uses the (POSIX) C strtod(3) which by design (or at least by the manual page description :) follows this heuristic (from the start of the char* passed parse off as many digits followed by an optional "." and more digits followed by an optional exponent notation, and stop when you hit a not-digit-not-plusminus-not-exponent-marker character) rather than using if-looks_like_number-number-else-it's-zero. This is mentioned in perldata in passing, but if you're not familiar with the C API I'll grant that it's certainly open to causing confusion.

Re: is_numeric
by jdporter (Chancellor) on Apr 11, 2007 at 21:00 UTC

    Very clever.

    Perhaps too clever?

    print is_numeric([]) ? "yes\n" : "no\n";
    A word spoken in Mind will reach its own level, in the objective world, by its own weight
      return eval { ! ref $x and $x == $x };

      is a light weight way to fix that case.

      DWIM is Perl's answer to Gödel
        But if you do that, objects that overload numerification to return a number won't be considered numbers...
Log In?

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

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (5)
As of 2022-01-18 20:38 GMT
Find Nodes?
    Voting Booth?
    In 2022, my preferred method to securely store passwords is:

    Results (54 votes). Check out past polls.