我正在两个浮点变量之间进行一次乘法运算。之后,我需要检查数字溢出,下溢和除零错误(如果有的话)。
我怎么能这样做?
答案 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" }