2009-07-26 17 views

Odpowiedz

12

Oto dość niezawodny sposób:

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)); 
} 

wyjściowa wynosi:

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

dniu 5.10 i wyżej, gdzie biblioteka C wspiera go, tylko 0+ „NaN” , 0+ "inf" lub 0 + "- inf" też działa. – ysth

+1

Bardzo energiczny z ciebie: 13 minut temu, zadajesz pytanie; 11 minut temu, odpowiadasz; 9 minut temu, publikujesz komentarz. Powinieneś kupić sobie piwo lub coś takiego. – Telemachus

+0

@Telemachus: Z wyjątkiem tego, że nie piję rzeczy ... – ysth

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

EDIT: Fixed do minus nieskończoności.

+0

Ktoś, kto nie głosuje na tę odpowiedź, pozwala ci opuścić stanowisko, jeśli nie poczujesz się zawstydzony. W ten sposób działa absolutnie idealnie w perlu. Jeśli $ a jest liczbą reprezentującą ciąg znaków, będzie to "nan" lub "inf" tylko wtedy, gdy będzie to wartość NaN lub Inf. –

+0

Co, jeśli $ a nie jest liczbą, ale faktycznie jest łańcuchem "nan"? –

+0

@Ryan: String "nan" nie jest liczbą oczywiście. Rozwiązanie Ystha działa dokładnie tak samo. Sprawdź 'perl -le 'sub isnan {! zdefiniowany ($ _ [0] <=> 9 ** 9 ** 9)}; print isnan ("nan") ", jeśli mi nie ufasz. –

4

Osobiście użyłbym Math::BigFloat (lub BigInt) do wszystkiego, co ma dotknąć nieskończoności NaN.

Po co na nowo zaprojektować koło za pomocą rozwiązania do hackowania, gdy istnieją już moduły, które wykonują zadanie?

-3

Zwięzła odpowiedź, która działa.

1: Jak stworzyć "NAN" zmienną do wyjścia (do printf, na przykład):

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

2: Jak przetestować dla "NAN" (wygląda jak ASCII Art):

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

3: Jak stworzyć "INF" i INFN zmienne:

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

4: Jak przetestować dla "INF" (dowolnego znaku):

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

(1) i (3) nie różnią się od "$ NAN =" NAN "+1;', '$ INF =" INF "+1; $ INFN = - "INF"; 'po prostu bardziej gadatliwy – ysth

+0

oh, widzę (4) również używa barewords, tylko bez wyłączania strict. Wszystkie te, które polegają na tym, że ciągi takie jak "NAN" i "INF" stają się odpowiednią "liczbą" w kontekście liczbowym, zawiodą w starszych perls lub gdy środowisko wykonawcze C nie obsługuje tego (np. Strawberry perl lub activeperl w oknach) – ysth

+1

Odpowiedź "kompleksowa" obejmowałaby zestaw testowy. – dolmen

5

Użyj Data::Float z CPAN. Eksportuje następujące funkcje:

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

I w przeciwieństwie do innych rozwiązań pół pracy zamieszczone tutaj, to ma testsuite.

+0

Należy wspomnieć, że kontrola 'Data :: Float' dla' NaN' zależy od wsparcia 'NaN' na platformie. –

0

Kiedy szukałem mam ten serwis (tutaj) i http://www.learning-perl.com/2015/05/perls-special-not-a-numbers/

prowadzi link artykule wskazuje, że „nan” == „nan” nigdy nie jest prawdziwe, gdy instrumentem bazowym realizacja c obsługuje NaN ponieważ Nan nie może równać się .

to ładnie ilustrowany

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

Chyba ryzyko działa Ci kod w środowisku, w którym perla degradacji wdziękiem i kod nie może być wystarczająco niskie, aby nie martwić się zbytnio .

I oczywiście, jeśli nie chcesz Perl interpolować jako liczbę, użyj „eq” Nie „==”

Powiązane problemy