Question

Existe-t-il un moyen simple en Perl qui me permettra de déterminer si une variable donnée est numérique ?Quelque chose du genre :

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

serait idéal.Une technique qui ne lancera pas d'avertissements lorsque le -w Le commutateur utilisé est certainement préféré.

Était-ce utile?

La solution

Utiliser Scalar::Util::looks_like_number() qui utilise la fonction look_like_number() de l'API interne Perl C, qui est probablement le moyen le plus efficace de le faire.Notez que les chaînes « inf » et « infinity » sont traitées comme des nombres.

Exemple:

#!/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";
}

Donne ce résultat :

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

Voir également:

Autres conseils

Découvrez le module CPAN Expression rationnelle : Commun.Je pense qu'il fait exactement ce dont vous avez besoin et gère tous les cas extrêmes (par ex.nombres réels, notation scientifique, etc.).par exemple.

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

La question initiale était de savoir comment savoir si une variable était numérique et non si elle « a une valeur numérique ».

Il existe quelques opérateurs qui ont des modes de fonctionnement distincts pour les opérandes numériques et chaînes, où « numérique » désigne tout ce qui était à l'origine un nombre ou qui a déjà été utilisé dans un contexte numérique (par ex.dans $x = "123"; 0+$x, avant l'ajout, $x est une chaîne, elle est ensuite considérée comme numérique).

Une façon de le savoir est la suivante :

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

Une réponse simple (et peut-être simpliste) à la question est le contenu de $x numérique est le suivant:

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

Il fait une comparaison textuelle de l'original $x avec le $x converti en valeur numérique.

Habituellement, la validation des nombres se fait avec des expressions régulières.Ce code déterminera si quelque chose est numérique et vérifiera les variables non définies afin de ne pas lancer d'avertissements :

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

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

En voici quelques-uns matériel de lecture tu devrais regarder.

Pas parfait, mais vous pouvez utiliser une regex :

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

Je ne crois pas qu'il y ait quoi que ce soit de intégré pour le faire.Pour en savoir plus sur le sujet, consultez Perlmonks sur la détection numérique

Une expression régulière légèrement plus robuste peut être trouvée dans Expression rationnelle : Commun.

On dirait que vous voulez savoir si Perl pense qu'une variable est numérique.Voici une fonction qui intercepte cet avertissement :

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

Une autre option consiste à désactiver l'avertissement localement :

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

Notez que les variables non numériques seront converties silencieusement en 0, ce qui est probablement ce que vous vouliez de toute façon.

rexep pas parfait...c'est:

use Try::Tiny;

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

Essaye ça:

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

Mais j'ai trouvé ça intéressant

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

Personnellement, je pense que la voie à suivre est de s'appuyer sur le contexte interne de Perl pour rendre la solution à toute épreuve.Une bonne expression rationnelle pourrait correspondre à toutes les valeurs numériques valides et à aucune des valeurs non numériques (ou vice versa), mais comme il existe un moyen d'employer la même logique que celle utilisée par l'interpréteur, il devrait être plus sûr de s'y fier directement.

Comme j'ai tendance à exécuter mes scripts avec -w, j'ai dû combiner l'idée de comparer le résultat de "valeur plus zéro" à la valeur d'origine avec le no warnings approche basée sur @ysth :

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

Vous pouvez utiliser des expressions régulières pour déterminer si $foo est un nombre (ou non).

Jetez un oeil ici:Comment déterminer si un scalaire est un nombre

if (défini $ x && $ x! ~ m / d /) {} ou $ x = 0 si!$x ;si ( $x !~ m/\D/) {}

Il s'agit d'une légère variation de la réponse de Veekay, mais permettez-moi d'expliquer mon raisonnement pour ce changement.

L’exécution d’une expression régulière sur une valeur non définie entraînera une propagation d’erreurs et entraînera la fermeture du code dans de nombreux environnements, sinon la plupart.Tester si la valeur est définie ou définir un cas par défaut comme je l'ai fait dans l'exemple alternatif avant d'exécuter l'expression enregistrera, au minimum, votre journal des erreurs.

Cette fonction fonctionne pour moi :

    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;
    }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top