如何在 Perl 中创建或测试 NaN 或无穷大?

Posted

技术标签:

【中文标题】如何在 Perl 中创建或测试 NaN 或无穷大?【英文标题】:How do I create or test for NaN or infinity in Perl? 【发布时间】:2010-11-14 05:21:40 【问题描述】:

如何在 Perl 中创建或测试 NaN 或无限值?

【问题讨论】:

【参考方案1】:
print "Is NaN\n" if $a eq 'nan';
print "Is Inf\n" if $a eq 'inf' or $a eq '-inf';

编辑:固定为负无穷。

【讨论】:

如果$a不是数字,而是字符串“nan”怎么办? @Ryan:字符串“nan”当然不是数字。 ysth 的解决方案完全相同。如果您不信任我,请查看perl -le 'sub isnan ! defined( $_[0] <=> 9**9**9 ) ; print isnan("nan")' Inf 不是很完美,您还需要检查“-inf”。 您需要在比较之前将 lc 运算符应用于 $a,因为实际的字符串是“Inf”而不是“inf”。 最近11年好像变了。【参考方案2】:

这是一个相当可靠的方法:

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

输出是:

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

【讨论】:

在 C 库支持的 5.10 及更高版本上,仅 0+"nan"、0+"inf" 或 0+"-inf" 也可以工作。 @daotoad:是的,只是一个简单的方法。不幸的是,有些代码使用了 100**1000 之类的东西,它在 IEEE 双精度下是无限的,但在长双精度下不是无限的。 只是不要在 bigint 下使用它,否则您会想知道为什么您的程序会挂起。 对,在 bigint 下,使用 Math::BigInt->bnan()、->binf() 或 ->binf('-')。 我更关心有人打开了 bigint 而你没有注意到的情况。 :)【参考方案3】:

使用来自 CPAN 的 Data::Float。它导出以下函数:

float_is_infinite() float_is_nan() ...

与此处发布的其他半工作解决方案相反,它有一个testsuite。

【讨论】:

需要说明的是,Data::Floats 对NaN 的检查依赖于平台对NaN 的支持。【参考方案4】:

就个人而言,我会使用Math::BigFloat(或BigInt)来处理任何会触及NaN 的无穷大的东西。

既然已经有模块可以完成这项工作,为什么还要用 hack 解决方案重新发明***?

【讨论】:

【参考方案5】:

当我搜索时,我得到了这个网站(这里)和http://www.learning-perl.com/2015/05/perls-special-not-a-numbers/

链接的文章指出,当底层 c 实现支持 NaN 因为 Nan 无法匹配自身时,“nan” == “nan” 永远不会为真。

这很好地说明了

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

我猜想在 perl 已经正常降级而你的代码还没有降级的环境中运行你的代码的风险可能足够低,所以你不必太担心。

当然,如果您不希望 perl 插入数字,请使用 'eq' 而不是 '=='

【讨论】:

【参考方案6】:

以下是有效的简洁答案。

1:如何为输出创建一个“NAN”变量(例如到 printf):

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

2:如何测试“NAN”(看起来像 ascii 艺术):

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

3:如何创建“INF”和INFN变量:

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

4:如何测试“INF”(任何符号):

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

【讨论】:

(1) 和 (3) 与 $NAN = "NAN"+1;$INF = "INF"+1; $INFN = -"INF"; 没有区别,只是更冗长 哦,我看到 (4) 也使用了裸词,只是没有禁用严格。所有这些依赖于像“NAN”和“INF”这样的字符串成为数字上下文中适当的“数字”的所有这些都将在旧的perls或C运行时不支持它的地方失败(例如,草莓perl或windows上的activeperl) 一个全面的答案将包括一个测试套件。 将其更改为更清晰...这是一个简洁,正确的答案。也适用于 activeperl/windows 等。 我删除了所有的裸词

以上是关于如何在 Perl 中创建或测试 NaN 或无穷大?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用“如果存在”在 MySQL 中创建或删除索引?

DSharpPlus 如何在 C# 中创建或设置不和谐频道到 NSFW

如何在自定义 Xcode 项目模板中创建或定义新目标

如何使用看门狗监视在Python中创建或删除的文件的时间

如何结合突变在 django-graphql-jwt 中创建或登录用户?

在使用管道进行预处理后,如何解决“输入包含 NaN、无穷大或对于 dtype('float64') 而言太大的值”?