2009-07-26 13 views

Respuesta

12

Aquí está una manera bastante fiable:

my $inf = 9**9**9; 
my $neginf = -9**9**9; 
my $nan = -sin(9**9**9); 

sub isinf { $_[0]==9**9**9 || $_[0]==-9**9**9 } 
sub isnan { ! defined($_[0] <=> 9**9**9) } 
# useful for detecting negative zero 
sub signbit { substr(sprintf('%g', $_[0]), 0, 1) eq '-' } 

for my $num ($inf, $neginf, $nan) { 
    printf("%s:\tisinf: %d,\tisnan: %d,\tsignbit: %d\n", $num, isinf($num), isnan($num), signbit($num)); 
} 

de salida es:

inf: isinf: 1, isnan: 0, signbit: 0 
-inf: isinf: 1, isnan: 0, signbit: 1 
nan: isinf: 0, isnan: 1, signbit: 0 
+5

En 5.10 y arriba, donde está la biblioteca C soporta, simplemente 0+ "nan" , 0+ "inf", o 0 + "- inf" también funcionan. – ysth

+1

Muy enérgico de ti: hace 13 minutos, haces la pregunta; Hace 11 minutos, lo respondes; Hace 9 minutos, publicaste un comentario. Deberías comprarte una cerveza o algo así. – Telemachus

+0

@Telemachus: Excepto que no bebo nada ... – ysth

14
print "Is NaN\n" if $a eq 'nan'; 
print "Is Inf\n" if $a eq 'inf' or $a eq '-inf'; 

EDITAR: Se ha corregido para infinito negativo.

+0

Quien abajo vote esta respuesta, le permitirá dejar la publicación si no se siente avergonzado. De esta manera, funciona absolutamente perfecto en Perl. Si $ a es el número que la representación de cadena será 'nan' o 'inf' solo si es valor NaN o Inf. –

+0

¿Qué pasa si $ a no es un número, pero en realidad es la cadena "nan"? –

+0

@Ryan: String "nan" no es un número de curso. La solución de ysth funciona exactamente igual. Marque 'perl -le 'sub isnan {! definido ($ _ [0] <=> 9 ** 9 ** 9)}; print isnan ("nan") '' si no confías en mí. –

4

Personalmente, yo usaría Math::BigFloat (o BigInt) para cualquier cosa que vaya a tocar el infinito de NaN.

¿Por qué reinventar la rueda con una solución de hack cuando ya hay módulos que hacen el trabajo?

-3

Respuesta sucinta que funciona de la siguiente manera.

1: Cómo crear una variable "NAN" para la salida (a printf, por ejemplo):

{no strict 'subs'; $NAN="NAN"+1;} 

2: Cómo probar para "NAN" (se parece a arte ASCII):

sub isnan {!($_[0]<=0||$_[0]>=0)} 

3: Cómo crear un "INF" y las variables: INFN

{$INF="INF"+1; $INFN=-"INF"+1} 

4: Cómo probar para "INF" (de cualquier signo):

sub isinf {($_[0]==+"INF")||($_[0]==-"INF")} 
+1

(1) y (3) no son diferentes de '$ NAN =" NAN "+1;', '$ INF =" INF "+1; $ INFN = - "INF"; 'simplemente más detallado – ysth

+0

oh, veo que (4) usa también palabras sin contraseña, solo sin deshabilitar estrictamente. Y todos estos que dependen de cadenas como "NAN" e "INF" convirtiéndose en el "número" apropiado en contexto numérico fallarán en perls anteriores o cuando el tiempo de ejecución de C no lo soporte (por ejemplo, fresa perl o activeperl en Windows) – ysth

+1

Una _comprehensive_ respuesta incluiría una suite de pruebas. – dolmen

5

Use Data::Float de CPAN. Exporta las siguientes funciones:

  • float_is_infinite()
  • float_is_nan()
  • ...

Y al contrario de las otras soluciones de medio de trabajo publicadas aquí, que tiene un testsuite.

+0

Debe mencionarse que 'Data :: Float's cheque para' NaN' depende del soporte 'NaN' en la plataforma. –

0

cuando busqué Tengo este sitio (aquí) y http://www.learning-perl.com/2015/05/perls-special-not-a-numbers/

El artículo enlazado señala que "nan" == "nan" nunca es cierto, cuando la implementación subyacente c apoya NaN porque Nan no puede igualar en sí .

Esto ilustra muy bien con

die "This perl does not support NaN!\n" if "NaN" == "NaN"; 

supongo que el riesgo de que la ejecución de código en un entorno en el Perl se ha degradado con gracia y su código no se puede ser lo suficientemente bajo como para que no se preocupa demasiado .

Y por supuesto, si usted no quiere Perl para interpolar como un número, utilice 'eq' no '=='

Cuestiones relacionadas