Verwenden Sie Scalar::Util::looks_like_number()
diese Option, um die Funktion look_like_number () der internen Perl C-API zu verwenden. Dies ist wahrscheinlich der effizienteste Weg, dies zu tun. Beachten Sie, dass die Zeichenfolgen "inf" und "unendlich" als Zahlen behandelt werden.
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:
perldoc perlapi
Wenn Sie dem Pfad folgen, erfahren Sie: Testen Sie, ob der Inhalt eines SV wie eine Zahl aussieht (oder eine Zahl ist). "Inf" und "Infinity" werden als Zahlen behandelt (es wird also keine nicht numerische Warnung ausgegeben), auch wenn Ihr atof () sie nicht erfasst. Kaum eine testbare Spezifikation ...0x12
werden bei diesem Test nicht als Zahlen betrachtet.Schauen Sie sich das CPAN-Modul Regexp :: Common an . Ich denke, es macht genau das, was Sie brauchen, und behandelt alle Randfälle (z. B. reelle Zahlen, wissenschaftliche Notation usw.). z.B
quelle
Die ursprüngliche Frage war, wie man erkennt, ob eine Variable numerisch ist, nicht, ob sie "einen numerischen Wert hat".
Es gibt einige Operatoren, die getrennte Betriebsmodi für numerische und Zeichenfolgenoperanden haben, wobei "numerisch" alles bedeutet, was ursprünglich eine Zahl war oder jemals in einem numerischen Kontext verwendet wurde (z. B. in
$x = "123"; 0+$x
, bevor die Addition$x
eine Zeichenfolge ist, danach wird als numerisch betrachtet).Eine Möglichkeit zu sagen ist folgende:
Wenn die bitweise Funktion aktiviert ist, die
&
nur einen numerischen Operator erstellt und einen separaten Zeichenfolgenoperator hinzufügt&.
, müssen Sie sie deaktivieren:(bitweise ist in Perl 5.022 und höher verfügbar und standardmäßig aktiviert, wenn Sie
use 5.028;
oder höher.)quelle
sub numeric { $obj = shift; no warnings "numeric"; return eval('length($obj & "")'); }
my $obj = shift;
. Warum die Bewertung?my $obj = shift
natürlich verwendet, habe es einfach nicht richtig von meinem Code auf den Kommentar übertragen, ich habe es ein bisschen bearbeitet. Allerdingssub numeric { my $obj = shift; no warnings "numeric"; return length($obj & ""); }
erzeugt die gleichen Fehler. Natürlich würde eine geheime globale Variable das Verhalten erklären, genau das würde ich in diesem Fall erwarten, aber leider ist es nicht so einfach. Auch das würde vonstrict
& gefangen werdenwarnings
. Ich habe die Auswertung in einem ziemlich verzweifelten Versuch versucht, den Fehler zu beseitigen, und es hat funktioniert. Keine tieferen Überlegungen, nur Versuch und Irrtum.sub numeric { my $obj = shift; no warnings "numeric"; return length($obj & ""); }
print numeric("w") . "\n"; #=>0
,print numeric("x") . "\n"; #=>0
,print numeric("1") . "\n"; #=>0
,print numeric(3) . "\n"; #=>1
,print numeric("w") . "\n"; #=>1
. Wenn Sie eine Auswertung ('') um die Länge setzen, ergibt der letzte Ausdruck eine 0, wie es sollte. Stelle dir das vor.Eine einfache (und vielleicht vereinfachende) Antwort auf die Frage lautet: Der Inhalt der
$x
numerischen lautet wie folgt:Es wird ein Textvergleich des Originals
$x
mit dem$x
in einen numerischen Wert konvertierten Wert durchgeführt.quelle
$x eq (($x+0)."")
ein schlimmeres Problem ist jedoch, dass unter dieser Funktion "1.0" nicht numerisch istNormalerweise erfolgt die Validierung von Zahlen mit regulären Ausdrücken. Dieser Code bestimmt, ob etwas numerisch ist, und sucht nach undefinierten Variablen, um keine Warnungen auszulösen:
Hier ist etwas Lesematerial, das Sie sich ansehen sollten.
quelle
\d*\.?\d+
Teil führt ein ReDoS- Risiko ein. Ich empfehle/^[+-]?(?!\.(?!\d)|$)\d*(?:\.\d*)?$/
oder füge stattdessen/^[+-]?(?!\.(?!\d)|$)\d*(?:\.\d*)?(?:(?<=[\d.])e[+-]?\d+)?$/i
eine wissenschaftliche Notation ( Erklärung und Beispiele ) hinzu. Dies verwendet einen doppelt negativen Lookahead, um zu verhindern, dass Zeichenfolgen wie.
und.e0
als Zahlen übergeben werden. Es wird auch ein positives Aussehen verwendet, um sicherzustellen, dasse
eine Zahl folgt.Nicht perfekt, aber Sie können einen regulären Ausdruck verwenden:
quelle
Ich glaube nicht, dass etwas eingebaut ist, um es zu tun. Weitere Informationen zu diesem Thema finden Sie unter Perlmonks zum Erkennen von Zahlen
quelle
Eine etwas robustere Regex finden Sie in Regexp :: Common .
Es hört sich so an, als ob Sie wissen möchten, ob Perl eine Variable für numerisch hält. Hier ist eine Funktion, die diese Warnung abfängt:
Eine andere Möglichkeit besteht darin, die Warnung lokal auszuschalten:
Beachten Sie, dass nicht numerische Variablen stillschweigend in 0 konvertiert werden, was wahrscheinlich sowieso das ist, was Sie wollten.
quelle
rexep nicht perfekt ... das ist:
quelle
Versuche dies:
quelle
Ich fand das allerdings interessant
quelle
Persönlich denke ich, dass der Weg dahin darin besteht, sich auf den internen Kontext von Perl zu verlassen, um die Lösung kugelsicher zu machen. Ein guter regulärer Ausdruck könnte mit allen gültigen numerischen Werten und keinem der nicht numerischen Werte übereinstimmen (oder umgekehrt). Da es jedoch eine Möglichkeit gibt, dieselbe Logik zu verwenden, die der Interpreter verwendet, sollte es sicherer sein, sich direkt darauf zu verlassen.
Da neige ich dazu, meine Skripte mit auszuführen
-w
, musste ich die Idee, das Ergebnis von "Wert plus Null" mit dem ursprünglichen Wert zu vergleichen, mit demno warnings
basierten Ansatz von @ysth kombinieren:quelle
Sie können reguläre Ausdrücke verwenden, um festzustellen, ob $ foo eine Zahl ist (oder nicht).
Schauen Sie hier: Wie bestimme ich, ob ein Skalar eine Zahl ist?
quelle
if (definiert $ x && $ x! ~ m / \ D /) {} oder $ x = 0 if! $ x; if ($ x! ~ m / \ D /) {}
Dies ist eine geringfügige Abweichung von Veekays Antwort, aber lassen Sie mich meine Gründe für die Änderung erläutern.
Das Ausführen eines regulären Ausdrucks für einen undefinierten Wert führt zu Fehlern und führt dazu, dass der Code in vielen, wenn nicht in den meisten Umgebungen beendet wird. Wenn Sie testen, ob der Wert definiert ist, oder einen Standardfall festlegen, wie ich es im alternativen Beispiel getan habe, bevor Sie den Ausdruck ausführen, wird mindestens Ihr Fehlerprotokoll gespeichert.
quelle