tags:

views:

329

answers:

2

Hi All,

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?

+3  A: 

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;
}
bobbymcr
Negative infinity is an overflow, not an underflow. An underflow is something quite different: http://en.wikipedia.org/wiki/Arithmetic_underflow
ysth
Also, the 1.#INF thing is a Microsoft perversion. The POSIX standard says: 'an infinity shall be converted in one of the styles "[-]inf" or "[-]infinity" ; which style is implementation-defined.' So /inf/i would be a better test.
ysth
Thanks, I've corrected my answer.
bobbymcr
+1  A: 

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" }
ysth
Thanks for all of you who tried to help me....