Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

perl inconsistent negative zero result

I have the following code :

my $m=0;
my $e =0 ;
my $g=0;

my $x=  sprintf( "%0.1f", (0.6*$m+ 0.7 * $e-1.5)*$g);

print $x; 

when I run the script the result is -0.0 and not 0.0 could someone explain why and how i can change it to be 0.0.

like image 451
smith Avatar asked Oct 12 '11 21:10

smith


3 Answers

First, this has nothing to do with Perl. It's your processor that's returning -0.0. You'll see this same behaviour in other languages.


You ask why, presumably asking why this is useful. Honestly, I don't know. Some scientists and engineers probably take advantage of it.

+0.0 would indicate "zero or something very slightly larger on the positive side".

-0.0 would indicate "zero or something very slightly larger on the negative side."


You also ask how to get rid of the sign.

Negative zero is false, so $x || 0 does the trick.

like image 142
ikegami Avatar answered Oct 30 '22 13:10

ikegami


You've run into something very strange. My first thought was that you were seeing some very small negative number that sprintf rounds to -0.0, but in fact the result of the expression is an actual negative zero.

Here's a simpler program that exhibits the same issue:

#!/usr/bin/perl

use strict;
use warnings;

my $x = -1.0 * 0.0;
my $y = -1.5 * 0.0;
printf "x = %f\n", $x;
printf "y = %f\n", $y;

and the output:

x = 0.000000
y = -0.000000

My best guess is that -1.0 * 0.0 is being computed at compile time, but -1.5 * 0.0 is being computed at execution time, and the computations are yielding different results. EDIT: Strike that; a modified version of the program that replaces all the constants with function calls has the same behavior.

I can avoid the negative zero display by adding these lines before the printf calls:

$x += 0.0;
$y += 0.0;

but that's ugly.

(Incidentally, I get the same results with the "bleading-edge" version of Perl 5.15.2 from about a month ago.)

A similar C program prints -0.000000 for both x and y.

EDIT: Further experiment shows that multiplying a negative integral value by 0.0 yields 0.0, but multiplying a negative non-integral value by 0.0 yields -0.0. I've submitted a Perl bug report.

like image 3
Keith Thompson Avatar answered Oct 30 '22 12:10

Keith Thompson


Nothing to see here, move along...

Zero is represented by the exponent emin - 1 and a zero significand. Since the sign bit can take on two different values, there are two zeros, +0 and -0.

http://download.oracle.com/docs/cd/E19957-01/806-3568/ncg_goldberg.html

like image 1
piotr Avatar answered Oct 30 '22 12:10

piotr