tags:

views:

1233

answers:

3

How do I create or test for NaN or infinite values in Perl?

+5  A: 

Here's a fairly reliable way:

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

Output is:

inf:    isinf: 1, isnan: 0, signbit: 0
-inf:   isinf: 1, isnan: 0, signbit: 1
nan:    isinf: 0, isnan: 1, signbit: 0
ysth
On 5.10 and above, where the C library supports it, just 0+"nan", 0+"inf", or 0+"-inf" work too.
ysth
Very energetic of you: 13 minutes ago, you ask the question; 11 minutes ago, you answer it; 9 minutes ago, you post a comment. You should buy yourself a beer or something.
Telemachus
@Telemachus: Except that I don't drink the stuff...
ysth
Interesting, where does the 9 to the 9th to the 9th power come from? Is there a special significance or is it just an easy way to get a number big enough to blow up a variety of float specifications?
daotoad
@daotoad: yes, just an easy way. Some code unfortunately used things like 100**1000, which is infinite with IEEE double precision, but not infinite with long doubles.
ysth
Just don't use this under bigint or you'll wonder why your program is hung.
brian d foy
Right, under bigint, use Math::BigInt->bnan(), ->binf(), or ->binf('-').
ysth
I was more concern with cases where someone turned on bigint and you didn't notice. :)
brian d foy
+4  A: 
print "Is NaN\n" if $a eq 'nan';
print "Is Inf\n" if $a eq 'inf';
Hynek -Pichi- Vychodil
One who down vote this answer, let you leave post if you not feel ashamed. This way works absolutely perfect in perl. If $a is number than string representation will be 'nan' or 'inf' only if it is NaN or Inf value.
Hynek -Pichi- Vychodil
What if $a is not a number, but is actually the string "nan"?
Ryan Thompson
@Ryan: String "nan" is not a number of course. ysth's solution works exactly same. Check `perl -le 'sub isnan { ! defined( $_[0] <=> 9**9**9 ) }; print isnan("nan")'` if you don't trust me.
Hynek -Pichi- Vychodil
+2  A: 

Personally, I would use Math::BigFloat (or BigInt) for anything that is going to touch infinity of NaN.

Why reinvent the wheel with a hack solution when there are already modules that do the job?