php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #70804 Unary add on negative zero produces positive zero
Submitted: 2015-10-27 19:41 UTC Modified: 2015-12-19 02:11 UTC
From: davividal at gmail dot com Assigned: ajf
Status: Closed Package: *General Issues
PHP Version: 5.6.14 OS: Linux
Private report: No CVE-ID:
 [2015-10-27 19:41 UTC] davividal at gmail dot com
Description:
------------
Given a negative number, it's possible to turn it into positive by just putting a positive sign in front of it.

Test script:
---------------
var_dump(round(-1e-99));
var_dump(+round(-1e-99));


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-10-27 20:59 UTC] requinix@php.net
-Summary: Positive * Negative = Positive +Summary: round(-0)=-0 but +round(-0)=0
 [2015-10-27 20:59 UTC] requinix@php.net
Changed the summary. I take it you were originally seeing this with some multiplication?

It's not that the plus sign causes it to become positive. The same thing happens with a negative sign too: PHP recognizes the zero and forces it to be positive.

I don't know if this counts as a bug but it certainly could qualify as a request: while -0 is a legitimate (though unusual) floating-point number, I think that round(-0) should also force it to be positive.
 [2015-11-05 19:00 UTC] davividal at gmail dot com
After a bunch of operations I saw something like:

<?php
$var = round($foo - $bar);
$var = +$var;
?>

And wondered what was going on.

As for your statement that round() should turn the number into positive: that's what Ruby does, but not what Python does (I only tested on these 2). So I don't know what the correct behaviour should be here.

>>> foo = -1e-99
>>> round(foo)
-0.0
>>> +round(foo)
-0.0

irb(main):001:0> foo = -1e-99
=> -1.0e-99
irb(main):002:0> foo.round
=> 0
irb(main):003:0> +foo.round
=> 0

What I do know: +(-x) should be equal to -x. :)
 [2015-12-19 02:03 UTC] ajf@php.net
-Assigned To: +Assigned To: ajf
 [2015-12-19 02:03 UTC] ajf@php.net
I think this is a related problem to bug #52355: https://bugs.php.net/bug.php?id=52355

Unary plus in PHP is actually transformed by the compiler into adding zero. So +$a is effectively (0 + $a). Similarly, unary minus was transformed into subtracting from zero, so -$a is effectively (0 - $a).

However, it turned out that -$a and (0 - $a) don't behave exactly the same for floating-point in one specific case: negative zero. Evidently, this is also true for +$a and (0 + $a).

My solution for the -$a case was to transform it into (-1 * $a) instead, and that fixed that issue. It looks like we can use the same approach here, and +$a into (1 * $a), which doesn't mangle negative zero:

    $ sapi/cli/php -r 'var_dump(1 * round(-1e-99));'
    float(-0)

So, I'll write a patch to do this.
 [2015-12-19 02:11 UTC] ajf@php.net
-Summary: round(-0)=-0 but +round(-0)=0 +Summary: Unary add on negative zero produces positive zero
 [2015-12-19 02:11 UTC] ajf@php.net
I'm renaming the bug so it lines up with "Negating zero does not produce negative zero". The bug isn't really with round().
 [2015-12-19 02:35 UTC] ajf@php.net
Automatic comment on behalf of ajf@ajf.me
Revision: http://git.php.net/?p=php-src.git;a=commit;h=42c8f5e91d4e4ec00d91506e986e3578a3695ee9
Log: Fix bug #70804
 [2015-12-19 02:35 UTC] ajf@php.net
-Status: Assigned +Status: Closed
 [2015-12-19 02:35 UTC] ajf@php.net
Automatic comment on behalf of ajf@ajf.me
Revision: http://git.php.net/?p=php-src.git;a=commit;h=42c8f5e91d4e4ec00d91506e986e3578a3695ee9
Log: Fix bug #70804
 [2016-07-20 11:34 UTC] davey@php.net
Automatic comment on behalf of ajf@ajf.me
Revision: http://git.php.net/?p=php-src.git;a=commit;h=42c8f5e91d4e4ec00d91506e986e3578a3695ee9
Log: Fix bug #70804
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Fri Jul 21 08:01:41 2017 UTC