Comment puis-je savoir si une variable a une valeur numérique en Perl?
Est-il un moyen simple en Perl qui me permettra de déterminer si une variable est numérique? Quelque chose le long des lignes de:
if (is_number($x))
{ ... }
serait l'idéal. Une technique qui ne lancer des avertissements lorsque la -w
commutateur est utilisé est certainement préférable.
Vous devez vous connecter pour publier un commentaire.
Utilisation
Scalar::Util::looks_like_number()
qui utilise les internes de Perl C de l'API de looks_like_number() de la fonction, ce qui est probablement le moyen le plus efficace pour ce faire.Notez que les chaînes "inf" et "infini" sont traités comme des numéros.
Exemple:
Donne ce résultat:
Voir aussi:
looks_like_number
perldoc perlapi
nous dit: Tester si le contenu d'un SV ressemble à un numéro (ou un nombre). "Inf" et "Infini" sont traités comme des nombres (et ne sera donc pas question d'un non-numérique d'avertissement), même si votre atof() n'en connaît pas d'eux. À peine un testable spec...0x12
sont pas considérés comme des numéros par ce test.looks_like_number
expose le fonction c'est la même chose que ce que Perl utilise, par magie, convertir des chaînes en nombres. Des traits de soulignement, hexadécimal, octal et binaire les nombres ne sont autorisés que des littéraux dans la source, pas de chaînes, si par exemple la0+"0x15"
ne marche pas droit. (Notez quelooks_like_number("0 but true")
est vrai! 🙂 référence)Découvrez le module CPAN Regexp::Common. Je pense que c'est exactement ce dont vous avez besoin et gère tous les cas de bord (par exemple, des nombres réels, la notation scientifique, etc). par exemple,
La question initiale était de savoir comment savoir si une variable est numérique, pas si elle "a une valeur numérique".
Il y a un peu d'opérateurs qui ont séparé les modes de fonctionnement pour le numérique et la chaîne des opérandes, où "numérique" s'entend de tout ce qui a été à l'origine d'un nombre ou n'a jamais été utilisé dans un contexte numérique (par exemple, dans
$x = "123"; 0+$x
, avant l'ajout,$x
est une chaîne de caractères, par la suite, il est considéré comme numérique).Une façon de dire est ceci:
sub numeric { $obj = shift; no warnings "numeric"; return eval('length($obj & "")'); }
my $obj = shift;
. Pourquoi l'eval?my $obj = shift
, bien sûr, il suffit de ne pas le transférer correctement à partir de mon code pour le commentaire, j'ai édité un peu. Cependant,sub numeric { my $obj = shift; no warnings "numeric"; return length($obj & ""); }
produit la même erreur. Bien sûr, avoir un clandestin variable globale permettrait d'expliquer le comportement, c'est exactement ce que je m'attends dans ce cas, mais malheureusement, il n'est pas simple. Aussi, ce serait d'être pris parstrict
&warnings
. J'ai essayé le eval dans une tentative désespérée de se débarrasser de l'erreur, et cela a fonctionné. Pas plus loin le raisonnement, procès juste & erreur.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
. Si vous mettez un eval(") autour de la longueur, la dernière impression donnerait un 0, comme il se doit. Aller à la figure.Un simple (et peut-être simpliste) de répondre à la question est le contenu de
$x
numérique est la suivante:Il ne textuelle comparaison de l'original
$x
avec le$x
converti en valeur numérique.$x eq (($x+0)."")
cependant un problème plus grave, c'est que sous cette fonction, "1.0" n'est pas numériqueGénéralement le numéro de validation se fait avec des expressions régulières. Ce code permettra de déterminer si quelque chose est numérique ainsi que de vérifier pour des variables non définies à ne pas jeter avertissements:
Voici quelques matériel de lecture vous devriez regarder.
\d*\.?\d+
partie introduit une Rétablissements de risque. Je recommande/^[+-]?(?!\.(?!\d)|$)\d*(?:\.\d*)?$/
ou/^[+-]?(?!\.(?!\d)|$)\d*(?:\.\d*)?(?:(?<=[\d.])e[+-]?\d+)?$/i
pour inclure la notation scientifique (explication et des exemples) à la place. Il utilise un doublé d'anticipation négatif de prévenir aussi des chaînes de caractères comme.
et.e0
de passer par des nombres. Il utilise également un positif lookbehind pour assurer lae
suit un certain nombre.Pas parfait, mais vous pouvez utiliser une regex:
Je ne crois pas qu'il y a quelque chose builtin pour le faire. Pour plus que vous avez toujours voulu voir sur le sujet, voir Perlmonks sur la Détection Numérique
Un peu plus robuste regex peuvent être trouvés dans Regexp::Common.
Il semble que vous voulez savoir si Perl pense qu'une variable est numérique. Voici une fonction que les pièges de cette mise en garde:
Une autre option consiste à désactiver l'avertissement localement:
Noter que le non-variables numériques seront silencieusement converti à 0, ce qui est probablement ce que vous voulais de toute façon.
rexep pas parfait... c'est:
Essayez ceci:
J'ai trouvé cela intéressant, bien que
Personnellement, je pense que le chemin à parcourir est de s'appuyer sur Perl contexte interne pour faire la solution à l'épreuve des balles. Une bonne regexp peut correspondre à toutes les valeurs numériques valides et aucun des non-numériques (ou vice versa), mais comme il y a une façon d'utiliser la même logique de l'interprète est de l'utiliser doit être plus sûr de compter sur directement.
Comme j'ai tendance à exécuter mes scripts avec
-w
, j'ai eu de combiner l'idée de comparer le résultat de la "valeur plus zéro" à la valeur d'origine avec leno warnings
approche fondée sur @ysth:Vous pouvez utiliser des Expressions Régulières pour déterminer si $foo est un nombre (ou pas).
Prendre un coup d'oeil ici:
Comment puis-je déterminer si un scalaire est un nombre
si ( défini $x && $x !~ m/\D/) {}
ou
$x = 0 si ! $x;
if ( $x !~ m/\D/) {}
C'est une légère variation sur Veekay de la réponse, mais laissez-moi vous expliquer mon raisonnement pour le changement.
De l'exécution d'une expression rationnelle sur une valeur non définie provoque des erreurs de spew et entraîne le code de sortie à beaucoup, sinon la plupart des environnements. De tester si la valeur est définie ou l'établissement d'un cas par défaut comme je l'ai fait dans l'exemple de remplacement avant l'exécution de l'expression, au minimum, enregistrez votre journal des erreurs.
Cela fonctionne pour moi: