Come creare o testare NaN o valori infiniti in Perl?Come posso creare o testare NaN o infinito in Perl?
risposta
Ecco un modo abbastanza affidabile:
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));
}
uscita è:
inf: isinf: 1, isnan: 0, signbit: 0
-inf: isinf: 1, isnan: 0, signbit: 1
nan: isinf: 0, isnan: 1, signbit: 0
print "Is NaN\n" if $a eq 'nan';
print "Is Inf\n" if $a eq 'inf' or $a eq '-inf';
EDIT: fisso per infinito negativo.
Chi ha votato per votare, lascia che lasci la posta se non ti vergogni. In questo modo funziona assolutamente perfetto in perl. Se $ a è il numero, la rappresentazione della stringa sarà 'nan' o 'inf' solo se è NaN o Inf. –
Cosa succede se $ a non è un numero, ma in realtà è la stringa "nan"? –
@Ryan: String "nan" non è un numero certo. la soluzione di ysth funziona esattamente allo stesso modo. Controlla 'perl -le 'sub isnan {! definito ($ _ [0] <=> 9 ** 9 ** 9)}; print isnan ("nan") ''se non ti fidi di me. –
Personalmente, vorrei utilizzare Math::BigFloat
(o BigInt
) per tutto ciò che sta per toccare infinito di NaN
.
Perché reinventare la ruota con una soluzione di hack quando ci sono già moduli che fanno il lavoro?
Risposta succinta che segue.
1: Come creare una variabile "nan" per l'uscita (a printf, per esempio):
{no strict 'subs'; $NAN="NAN"+1;}
2: Come testare per "nan" (sembra ascii art):
sub isnan {!($_[0]<=0||$_[0]>=0)}
3: Come creare un "INF" e variabili INFN:
{$INF="INF"+1; $INFN=-"INF"+1}
4: Come testare per "INF" (di qualsiasi segno):
sub isinf {($_[0]==+"INF")||($_[0]==-"INF")}
(1) e (3) non sono diversi da solo '$ NAN =" NAN "+1;', '$ INF =" INF "+1; $ INFN = - "INF"; 'solo più verboso – ysth
oh, vedo (4) usa anche le bareword, solo senza disabilitare strict. E tutti questi che si basano su stringhe come "NAN" e "INF" diventando il "numero" appropriato in contesto numerico falliranno su perls precedenti o dove il runtime C non lo supporta (ad es. Perl fragola o activeperl su Windows) – ysth
Una risposta completa includerebbe una suite di test. – dolmen
Utilizzare Data::Float da CPAN. Essa esporta le seguenti funzioni:
float_is_infinite(
)float_is_nan()
- ...
E contrariamente alle altre soluzioni mezza di lavoro pubblicate qui, ha un testsuite.
Si deve menzionare che il controllo 'Data :: Float' per' NaN' dipende dal supporto 'NaN' sulla piattaforma. –
quando ho cercato ho ottenuto questo sito (qui) e http://www.learning-perl.com/2015/05/perls-special-not-a-numbers/
L'articolo collegato sottolinea che "nan" == "nan" non è mai vero, quando l'attuazione c sottostante supporta NaN perché Nan non può corrispondere per sé .
Questo è ben illustrato con
die "This perl does not support NaN!\n" if "NaN" == "NaN";
Credo che il rischio di voi l'esecuzione di codice in un ambiente dove il Perl ha degradato grazia e il codice non è potrebbe essere abbastanza basso in modo che non si preoccupi troppo .
E, naturalmente, se non si vuole perl a interpolare come un numero, utilizzare 'eq' non '=='
Su 5,10 e al di sopra, dove la libreria C supporta, basta 0+ "nan" , 0+ "inf", o 0 + "- inf" funzionano anche. – ysth
Molto energico da parte tua: 13 minuti fa, fai la domanda; 11 minuti fa, rispondi; 9 minuti fa, si pubblica un commento. Dovresti comprarti una birra o qualcosa del genere. – Telemachus
@Telemachus: Tranne che non bevo roba ... – ysth