How do I create or test for NaN or infinite values in Perl?
6 Answers
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
-
6On 5.10 and above, where the C library supports it, just 0+"nan", 0+"inf", or 0+"-inf" work too. – ysth Jul 26 '09 at 23:09
-
1Very 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 Jul 26 '09 at 23:21
-
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 Jul 27 '09 at 03:17
-
2@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 Jul 27 '09 at 03:31
-
9Just don't use this under bigint or you'll wonder why your program is hung. – brian d foy Jul 27 '09 at 04:17
-
6Right, under bigint, use Math::BigInt->bnan(), ->binf(), or ->binf('-'). – ysth Jul 27 '09 at 04:41
-
3I was more concern with cases where someone turned on bigint and you didn't notice. :) – brian d foy Jul 27 '09 at 21:57
-
-1 because any copy/pasted solution is bad. Use the CPAN. See my answer. – dolmen Mar 20 '13 at 14:51
-
1@dolmen Such a fundamental check should be possible without using the CPAN. It should be a core functionality. – Slaven Rezic Jun 10 '14 at 12:13
print "Is NaN\n" if $a eq 'nan';
print "Is Inf\n" if $a eq 'inf' or $a eq '-inf';
EDIT: Fixed for negative infinity.

- 26,174
- 5
- 52
- 73
-
2What if $a is not a number, but is actually the string "nan"? – Ryan C. Thompson Oct 06 '10 at 06:38
-
@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 Oct 06 '10 at 19:20
-
3
-
You need to apply the lc operator to $a before comparing, because the actual strings are things like "Inf" rather than "inf". – Dave Burton Jun 05 '21 at 20:57
-
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?

- 4,611
- 10
- 37
- 53

- 368
- 1
- 2
- 13
Use Data::Float from CPAN. It exports the following functions:
float_is_infinite(
)float_is_nan()
- ...
And contrary to the others half-working solutions posted here, it has a testsuite.

- 8,126
- 5
- 40
- 42
-
It should be mentioned that `Data::Float`s check for `NaN` is dependent on `NaN` support on the platform. – matthias krull Jul 25 '13 at 13:11
When I searched I got this site (here) and http://www.learning-perl.com/2015/05/perls-special-not-a-numbers/
The linked article points out that "nan" == "nan" is never true, when the underlying c implementation supports NaN because Nan cannot match itself.
This is nicely illustrated with
die "This perl does not support NaN!\n" if "NaN" == "NaN";
I guess the risk of running you code in an environment where perl has degraded gracefully and your code has not might be low enough so that you don't worry too much.
And of course if you don't want perl to interpolate as a number, use 'eq' not '=='

- 630
- 6
- 16
Succinct answer that works follows.
1: How to create a "NAN" variable for output (to printf, for example):
{no strict 'subs'; $NAN="NAN"+1;}
2: How to test for "NAN" (looks like ascii art):
sub isnan {!($_[0]<=0||$_[0]>=0)}
3: How to create an "INF" and INFN variables:
{$INF="INF"+1; $INFN=-"INF"+1}
4: How to test for "INF" (of any sign):
sub isinf {($_[0]==+"INF")||($_[0]==-"INF")}

- 11,620
- 5
- 64
- 44
-
1(1) and (3) are no different than just `$NAN = "NAN"+1;`, `$INF = "INF"+1; $INFN = -"INF";` just more verbose – ysth Oct 19 '12 at 19:07
-
oh, I see (4) uses barewords too, only without disabling strict. And all of these that rely on strings like "NAN" and "INF" becoming the appropriate "number" in numeric context will fail on older perls or where the C runtime doesn't support it (e.g. strawberry perl or activeperl on windows) – ysth Oct 19 '12 at 19:42
-
1
-
Changed it to be more clear... it's a succinct, correct answer. Also works on activeperl/windows, etc. – Erik Aronesty Mar 22 '13 at 12:52
-
You don't need the `no strict 'subs'` anymore if you don't use barewords. So your solution (still without testsuite) could be more succint. And `isinf` is still not efficient. – dolmen Apr 09 '13 at 16:40
-
1