如何在Perl中检查数字溢出和下溢情况?

时间:2009-09-08 07:03:04

标签: perl numbers

我正在两个浮点变量之间进行一次乘法运算。之后,我需要检查数字溢出,下溢和除零错误(如果有的话)。

我怎么能这样做?

2 个答案:

答案 0 :(得分:3)

这是一种检查溢出的方法(实际上只是浮点+无限和-Infinity):

#!perl -w
use strict;

my $x = 10 ** 200;
my $positive_overflow = $x * $x;
my $negative_overflow = -$x * $x;

print is_infinity($positive_overflow) ? 'true' : 'false';
print "\n";
print is_infinity($negative_overflow) ? 'true' : 'false';
print "\n";

sub is_infinity
{
    my $x = shift;
    return $x =~ /inf/i;
}

除零是很棘手的,因为你不能在正常的程序范围内实际执行除法而不会让你死。您可以将其包装在eval中:

#!perl -w
use strict;

my $x = 100;
my $y = 0;

my $q = try_divide($x, $y);
print "Might be division by zero...\n" if !defined $q;

$y = 10;
$q = try_divide($x, $y);
print "$q\n";

sub try_divide
{
    my $x = shift;
    my $y = shift;
    my $q;

    eval { $q = $x / $y };

    return $q;
}

答案 1 :(得分:1)

如果您的被除数为非零且您的商(结果)为零,则您有一个下溢。 如果结果非零,则可以通过查找最接近1的数字并将非结果乘以它并查看其是否发生变化来检查下溢;如果它是一个次正规结果,它将保持不变,因为它将缺乏正常结果所具有的全部精度。

my $underflow_checker;
for ( my $i = 1; 1 + $i > 1; $i /= 2 ) { $underflow_checker = 1 + $i }
...
$x = 2**-520;
$y = 2**520;
$result = $x / $y;
if ( $result == 0 && $x != 0 || $result != 0 && $result * $underflow_checker == $result ) { print "Underflow!\n" }