skip to Main Content

In PHP there is a floating point negative zero, which compares identically to floating point positive zero -0.0 === 0.0, despite printing as different strings. There is no integer negative zero in PHP.

I’m writing an extended version of rounding functions and I’m trying to replicate PHP’s native behaviour as much as possible. I’m writing it with TDD methodology, so I need a way to verify my code is in line with the native PHP functions by returning negative zero where PHP returns negative zero.

<?php
var_dump(ceil(-0.5));
double(-0)

Is there any way of testing for -0.0 apart from:

  • converting it to a string (string)-0.0 === '-0'
  • serialising it serialize(-0.0) === 'd:-0;'

3

Answers


  1. Chosen as BEST ANSWER

    @njuffa suggested if (1 / $x === -INF), which works but throws a division by zero warning.

    @Manu-sh modified it to do the same thing without the warning by using the new "power of" operator: **

    <?php
    function is_negative_zero($x) {
      return $x ** -1 === -INF;
    }
    
    echo is_negative_zero(0.0)? "Yes": "No";
    echo PHP_EOL;
    
    echo is_negative_zero(-0.0)? "Yes": "No";
    echo PHP_EOL;
    

    Output:

    No
    Yes
    

  2. This work only for literals but not for variables:

    var_export(0.0 ** 0 == 1);
    var_export(-0.0 ** 0 == -1);
    

    But this seems to work also for variables:

    // return 1 for positive zero, -1 for negative zero
    // otherwise return 0
    function zero_sign(float $x): int {
    
        if (($y = ($x ** -1)) === -INF)
            return -1;
    
        return $y === INF;
    }
    
    var_export(zero_sign(-0.0) === -1);
    var_export(zero_sign(0.0)  ===  1);
    var_export(zero_sign(-1.0) ===  0);
    var_export(zero_sign(1.0)  ===  0);
    

    You can check by yourself that this follow the mathematics rules,
    here are the Wolframalpha results for -0.0 ** -1 and 0.0 ** -1

    Login or Signup to reply.
  3. Floating point numbers have a specific bit that is set in the internal coding if it is negative. This test is also suitable to distinguish between +0.0 and -0.0. The test is also independent of how PHP performs operations with -0.0 and +0.0.

    function isNegativFloat($value){
      return is_float($value) AND ord(pack('E',$value)) & 0x80;
    }
    

    Examples:

    var_dump(isNegativFloat(0.0));  //bool(false)
    var_dump(isNegativFloat(-0.0));  //bool(true)
    var_dump(isNegativFloat(0.6));  //bool(false)
    var_dump(isNegativFloat(-0.6));  //bool(true)
    

    Special test for negative float zero:

    function isNegativFloatNull($value){
      return $value === 0.0 AND isNegativFloat($value);
    }
    

    Examples:

    var_dump(isNegativFloatNull(0.0));  //bool(false)
    var_dump(isNegativFloatNull(-0.0));  //bool(true)
    var_dump(isNegativFloatNull(0.6));  //bool(false)
    var_dump(isNegativFloatNull(-0.6));  //bool(false)
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search