Pregunta

¿Existe una forma sencilla en Perl que me permita determinar si una variable determinada es numérica?Algo parecido a:

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

Sería ideal.Una técnica que no arrojará advertencias cuando el -w Sin duda se prefiere el tipo de interruptor que se está utilizando.

¿Fue útil?

Solución

Usar Scalar::Util::looks_like_number() que utiliza la función looks_like_number() de la API interna de Perl C, que es probablemente la forma más eficiente de hacer esto.Tenga en cuenta que las cadenas "inf" e "infinity" se tratan como números.

Ejemplo:

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

Da esta salida:

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

Ver también:

Otros consejos

Consulte el módulo CPAN expresión regular::común.Creo que hace exactamente lo que necesitas y maneja todos los casos extremos (p. ej.números reales, notación científica, etc.).p.ej.

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

La pregunta original era cómo saber si una variable era numérica, no si "tiene un valor numérico".

Hay algunos operadores que tienen modos de operación separados para operandos numéricos y de cadena, donde "numérico" significa cualquier cosa que originalmente era un número o que alguna vez se usó en un contexto numérico (p. ej.en $x = "123"; 0+$x, antes de la adición, $x es una cadena, luego se considera numérico).

Una forma de saberlo es esta:

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

Una respuesta simple (y tal vez simplista) a la pregunta es el contenido de $x numérico es el siguiente:

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

Hace una comparación textual del original. $x con el $x convertido a un valor numérico.

Normalmente la validación de números se realiza con expresiones regulares.Este código determinará si algo es numérico y comprobará si hay variables no definidas para no generar advertencias:

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

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

aquí hay algunos material de lectura deberías mirar.

No es perfecto, pero puedes usar una expresión regular:

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

No creo que haya nada integrado para hacerlo.Para obtener más información de lo que siempre quiso ver sobre el tema, consulte Perlmonks sobre la detección de números

Se puede encontrar una expresión regular ligeramente más robusta en expresión regular::común.

Parece que quieres saber si Perl cree que una variable es numérica.Aquí hay una función que atrapa esa advertencia:

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

Otra opción es desactivar la advertencia localmente:

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

Tenga en cuenta que las variables no numéricas se convertirán silenciosamente a 0, que probablemente sea lo que deseaba de todos modos.

rexep no es perfecto...esto es:

use Try::Tiny;

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

Prueba esto:

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

Aunque encontré esto interesante.

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

Personalmente, creo que el camino a seguir es confiar en el contexto interno de Perl para que la solución sea a prueba de balas.Una buena expresión regular podría coincidir con todos los valores numéricos válidos y ninguno de los no numéricos (o viceversa), pero como hay una manera de emplear la misma lógica que usa el intérprete, debería ser más seguro confiar en eso directamente.

Como tiendo a ejecutar mis scripts con -w, tuve que combinar la idea de comparar el resultado del "valor más cero" con el valor original con el no warnings enfoque basado en @ysth:

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

Puede utilizar expresiones regulares para determinar si $foo es un número (o no).

Échale un vistazo aquí:¿Cómo puedo determinar si un escalar es un número?

if (definido $ x && $ x! ~ m/ d/) {} o $ x = 0 if!$x;si ( $x !~ m/\D/) {}

Esta es una ligera variación de la respuesta de Veekay, pero permítanme explicar el motivo del cambio.

Realizar una expresión regular en un valor indefinido provocará errores y hará que el código se cierre en muchos, si no en la mayoría, de los entornos.Probar si el valor está definido o establecer un caso predeterminado como lo hice en el ejemplo alternativo antes de ejecutar la expresión guardará, como mínimo, el registro de errores.

Esta función me funciona:

    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;
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top