Domanda

Esiste un modo semplice in Perl che mi permetterà di determinare se una determinata variabile è numerica?Qualcosa sulla falsariga di:

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

sarebbe l'ideale.Una tecnica che non genererà avvisi quando il -w l'interruttore è sicuramente preferibile.

È stato utile?

Soluzione

Utilizzo Scalar::Util::looks_like_number() che utilizza la funzione look_like_number() dell'API interna Perl C, che è probabilmente il modo più efficiente per farlo.Tieni presente che le stringhe "inf" e "infinity" vengono trattate come numeri.

Esempio:

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

Fornisce questo output:

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

Guarda anche:

Altri suggerimenti

Scopri il modulo CPAN Espressione regolare::Comune.Penso che faccia esattamente ciò di cui hai bisogno e gestisca tutti i casi limite (ad es.numeri reali, notazione scientifica, ecc.).per esempio.

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

La domanda originale era come sapere se una variabile era numerica, non se "ha un valore numerico".

Ci sono alcuni operatori che hanno modalità operative separate per operandi numerici e stringa, dove "numerico" significa tutto ciò che originariamente era un numero o è mai stato utilizzato in un contesto numerico (ad es.In $x = "123"; 0+$x, prima dell'aggiunta, $x è una stringa, poi viene considerata numerica).

Un modo per dirlo è questo:

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

Una risposta semplice (e forse semplicistica) alla domanda è il contenuto di $x numerico è il seguente:

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

Fa un confronto testuale dell'originale $x con il $x convertito in un valore numerico.

Di solito la convalida dei numeri viene eseguita con espressioni regolari.Questo codice determinerà se qualcosa è numerico e controllerà la presenza di variabili non definite per non generare avvisi:

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

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

Eccone alcuni materiale di lettura dovresti guardare.

Non perfetto, ma puoi usare una regex:

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

Non credo che ci sia qualcosa di integrato per farlo.Per più di quanto avresti mai voluto vedere sull'argomento, vedi Perlmonks sul rilevamento numerico

Una regex leggermente più robusta può essere trovata in Espressione regolare::Comune.

Sembra che tu voglia sapere se Perl ritiene che una variabile sia numerica.Ecco una funzione che intrappola questo avviso:

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

Un'altra opzione è disattivare l'avviso localmente:

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

Tieni presente che le variabili non numeriche verranno convertite silenziosamente in 0, che probabilmente è comunque ciò che volevi.

rexep non perfetto...questo è:

use Try::Tiny;

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

Prova questo:

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

L'ho trovato interessante però

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

Personalmente penso che la strada da percorrere sia fare affidamento sul contesto interno di Perl per rendere la soluzione a prova di proiettile.Una buona espressione regolare potrebbe corrispondere a tutti i valori numerici validi e a nessuno di quelli non numerici (o viceversa), ma poiché esiste un modo per utilizzare la stessa logica utilizzata dall'interprete, dovrebbe essere più sicuro fare affidamento direttamente su quello.

Poiché tendo a eseguire i miei script con -w, ho dovuto combinare l'idea di confrontare il risultato di "valore più zero" con il valore originale con il file no warnings approccio basato su @ysth:

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

Puoi utilizzare le espressioni regolari per determinare se $foo è un numero (o meno).

Dai un'occhiata qui:Come faccio a determinare se uno scalare è un numero

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

Questa è una leggera variazione sulla risposta di Veekay, ma lasciami spiegare il mio ragionamento per il cambiamento.

L'esecuzione di una regex su un valore non definito causerà l'emissione di errori e farà sì che il codice venga chiuso in molti se non nella maggior parte degli ambienti.Testare se il valore è definito o impostare un caso predefinito come ho fatto nell'esempio alternativo prima di eseguire l'espressione salverà, come minimo, il registro degli errori.

Questa funzione funziona per me:

    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;
    }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top