简体   繁体   中英

How do I check for numeric overflow and underflow conditions in Perl?

I am doing one multiplication operation between two float variables. After that i need to check for numeric overflow, underflow and divide by zero errors if any.

How I can do this?

Here's a way to check for overflow (which is actually just floating point +Infinity and -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;
}

Division by zero is tricky because you can't actually perform the division in normal program scope without having it die on you. You can wrap it in eval though:

#!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;
}

If your dividend is non-zero and your quotient (result) is zero, you've had an underflow. If your result is non-zero, underflow can be checked by finding the number closest to 1 and multiplying your non-result by it and seeing if it changes; if it was a subnormal result, it will remain unchanged, since it will lack the full range of precision a normal result would have.

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" }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM