Frage

Gibt es eine einfache Möglichkeit in Perl, die es mir ermöglichen, zu bestimmen, ob eine gegebene variable numerisch ist?Etwas entlang der Linien von:

if (is_number($x))
{ ... }

wäre ideal.Eine Technik, die nicht werfen Warnungen, wenn die -w - switch verwendet, ist sicherlich bevorzugt.

War es hilfreich?

Lösung

Verwenden Scalar::Util::looks_like_number() die nutzt die interne Perl-C-API ist looks_like_number () - Funktion, die ist wahrscheinlich der effizienteste Weg, dies zu tun.Beachten Sie, dass die Zeichenfolgen "inf" und "Unendlichkeit" sind als zahlen behandelt.

Beispiel:

#!/usr/bin/perl

use warnings;
use strict;

use Scalar::Util qw(looks_like_number);

my @exprs = qw(1 5.25 0.001 1.3e8 foo bar 1dd inf infinity);

foreach my $expr (@exprs) {
    print "$expr is", looks_like_number($expr) ? '' : ' not', " a number\n";
}

Gibt diese Ausgabe:

1 is a number
5.25 is a number
0.001 is a number
1.3e8 is a number
foo is not a number
bar is not a number
1dd is not a number
inf is a number
infinity is a number

Siehe auch:

Andere Tipps

Check out CPAN-Modul Regexp::Common.Ich denke, es ist genau das, was Sie benötigen, und kümmert sich um alle Sonderfälle (z.B.reelle zahlen, wissenschaftliche notation, etc.).z.B.

use Regexp::Common;
if ($var =~ /$RE{num}{real}/) { print q{a number}; }

Die ursprüngliche Frage war, wie zu sagen, wenn eine variable numerisch ist, nicht wenn es "hat einen numerischen Wert".

Es gibt einige Betreiber, die haben separate Betriebsarten für numerische und string-Operanden, wo "numeric" etwas bedeutet, war ursprünglich eine Zahl oder war je in einem numerischen Kontext (z.B.in $x = "123"; 0+$x, vor der Zugabe, $x ein string ist, danach ist es als numerisch).

Ein Weg, zu sagen, ist dies:

if ( length( do { no warnings "numeric"; $x & "" } ) ) {
    print "$x is numeric\n";
}

Eine einfache (und vielleicht vereinfachte) Antwort auf die Frage Inhalt $x numerische ist folgende:

if ($x  eq  $x+0) { .... }

Es hat einen textlichen Vergleich der original $x mit der $x in einen numerischen Wert umgewandelt.

Regel Nummer Validierung mit regulären Ausdrücken.Dieser code wird bestimmt, ob etwas numerische sowie Prüfung von undefinierten Variablen wie nicht zu werfen Warnungen:

sub is_integer {
   defined $_[0] && $_[0] =~ /^[+-]?\d+$/;
}

sub is_float {
   defined $_[0] && $_[0] =~ /^[+-]?\d+(\.\d+)?$/;
}

Hier sind einige lesestoff sollte man sich ansehen.

Nicht perfekt, aber Sie können einen regex verwenden:

sub isnumber 
{
    shift =~ /^-?\d+\.?\d*$/;
}

Ich glaube nicht, dass es etwas gibt, builtin, es zu tun.Für die mehr als Sie jemals wollte, um zu sehen, das zu diesem Thema finden Sie unter Perlmonks auf die Aufdeckung von Numerischen

Ein etwas robuster regex kann gefunden werden in Regexp::Common.

Es klingt wie Sie möchten wissen, ob Perl denkt, dass eine variable numerisch ist.Hier ist eine Funktion, die fallen, die Warnung:

sub is_number{
  my $n = shift;
  my $ret = 1;
  $SIG{"__WARN__"} = sub {$ret = 0};
  eval { my $x = $n + 1 };
  return $ret
}

Eine weitere option ist das deaktivieren der Warnung vor Ort:

{
  no warnings "numeric"; # Ignore "isn't numeric" warning
  ...                    # Use a variable that might not be numeric
}

Beachten Sie, dass nicht-numerischen Variablen werden automatisch in 0 konvertiert, das ist es wohl, was Sie wollte sowieso.

rexep nicht perfekt...dies ist:

use Try::Tiny;

sub is_numeric {
  my ($x) = @_;
  my $numeric = 1;
  try {
    use warnings FATAL => qw/numeric/;
    0 + $x;
  }
  catch {
    $numeric = 0;
  };
  return $numeric;
}

Versuchen Sie dies:

If (($x !~ /\D/) && ($x ne "")) { ... }

Ich fand das interessant, obwohl

if ( $value + 0 eq $value) {
    # A number
    push @args, $value;
} else {
    # A string
    push @args, "'$value'";
}

Ich persönlich denke, dass die Art und Weise zu gehen, ist darauf zu verlassen, Perl-internen Kontext, um die Lösung zu machen bullet-proof.Eine gute regexp könnte Spiel alle gültigen numerischen Werte und keines der nicht-numerischen (oder Umgekehrt), aber es ist ein Weg, der die Verwendung der gleichen Logik wird der interpreter mit Hilfe sollte es sicherer sein, auf die Sie sich verlassen, dass direkt.

Als ich Neige dazu, meine Scripte mit -w, Ich hatte zu kombinieren die Idee der Vergleich das Ergebnis des "value-plus-null", um den ursprünglichen Wert mit dem no warnings basierten Ansatz von @ysth:

do { 
    no warnings "numeric";
    if ($x + 0 ne $x) { return "not numeric"; } else { return "numeric"; }
}

Sie können Reguläre Ausdrücke verwenden, um zu bestimmen, wenn $foo ist eine Zahl (oder nicht).

Werfen Sie einen Blick hier:Wie kann ich feststellen, ob ein Skalar ist eine Zahl

if ( defined $x && $x !~ m/\D/ ) {} oder $x = 0, wenn !$x;if ( $x !~ m/\D/) {}

Dies ist eine leichte variation auf Veekay ' s Antwort, aber lassen Sie mich erklären, meine Begründung für die änderung.

Durchführung einer regex auf einen undefinierten Wert wird verursachen Fehler speien, und führen Sie den code, um zu beenden in vielen, wenn nicht den meisten Umgebungen.Testen ob der Wert definiert ist, oder das einrichten eines Standard-Fall, wie ich in der alternative B. vor dem ausführen der Ausdruck wird, auf ein minimum, speichern Sie Ihre Fehler-Protokoll.

Diese Funktion funktioniert für mich:

    sub IS_Integer() 
    {
        my $Text = shift;
        my $Integer = 0;

        if ($Text =~ /\D/)
        {
            $Integer = 1;
        }
        if ($Text =~ /^\d+$/)
        { 
            $Integer = 1;
        }
        if ($Text =~ /^-?\d+$/)       
        { 
            $Integer = 1;
        }
        if ($Text =~ /^[+-]?\d+$/)    
        { 
            $Integer = 1; 
        }
        if ($Text =~ /^-?\d+\.?\d*$/) 
        {
            $Integer = 1; 
        }
        if ($Text =~ /^-?(?:\d+(?:\.\d*)?&\.\d+)$/) 
        {
            $Integer = 1;
        }
        if ($Text =~ /^([+-]?)(?=\d&\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/)
        {
            $Integer = 1;
        }

        return $Integer;
    }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top