Search code examples
divide-by-zerophp-8

@ division by 0 returns fatal in PHP 8


In PHP 7 it returns INF which is okay but in PHP 8 onwards its returning a fatal error.

<?php
$a = 2;
$b = 0;
$c = @($a / $b);
echo $c;
echo "\n";
?>

Is there anyway to get PHP 8 return INF too ? I have a script where there are like 100 possible division by zero - I can't add 100 if conditions, I need the @ suppress to care of it.


Solution

  • This is one of the hidden braking changes if you rely on the value returned from dividing by 0.

    Generally, User @Alister Bulman already gave you the answer you're looking for. But if you need a backward compatible solution, read on. It is quite important to know how division by 0 works with different PHP versions.

    Consider the fallowing example:

    <?php
    
    echo "--- 2 / 0 ---". PHP_EOL;
    try{
        $res = 2 / 0;
    }catch(DivisionByZeroError $e){
        echo " ### Caught 2 / 0! ". $e->getMessage() . PHP_EOL;
        $res = "nothing returned - error thrown!";
    }
    echo "RETURNS: ";
    var_dump($res);
    echo " ### Continue script" . PHP_EOL;
    echo PHP_EOL;
    
    echo "--- intdiv(2, 0) ---". PHP_EOL;
    try{
        $res = intdiv(2, 0);
    }catch(DivisionByZeroError $e){
        echo " ### Caught intdiv(2, 0)!". $e->getMessage() . PHP_EOL;
        $res = "nothing returned - error thrown!";
    }
    echo "RETURNS: ";
    var_dump($res);
    echo " ### Continue script" . PHP_EOL;
    

    Depending on the PHP version, it will behave and return different values. See the example below for php8, php7 and php5.

    PHP8 / 0 would return (nothing - DivisionByZeroError thrown):

    --- 2 / 0 ---
    ### Caught 2 / 0! Division by zero
    RETURNS: string(32) "nothing returned - error thrown!"
    ### Continue script

    --- intdiv(2, 0) ---
    ### Caught intdiv(2, 0)! Division by zero
    RETURNS: string(32) "nothing returned - error thrown!"
    ### Continue script

    PHP7 / 0 would return INF
    and intdiv() return (nothing - DivisionByZeroError thrown):

    --- 2 / 0 ---
    Warning: Division by zero in /home/user/scripts/code.php on line 5
    RETURNS: float(INF)
    ### Continue script

    --- intdiv(2, 0) ---
    ### Caught intdiv(2, 0) !Division by zero
    RETURNS: string(32) "nothing returned - error thrown!"
    ### Continue script

    PHP5 / 0 would return FALSE:

    --- 2 / 0 ---
    Warning: Division by zero in /home/user/scripts/code.php on line 5
    RETURNS: bool(false)
    ### Continue script

    --- intdiv(2, 0) ---
    Fatal error: Call to undefined function intdiv() in /home/user/scripts/code.php on line 17

    So if you need to resolve the value of your division by 0 in PHP8 to INF and make it backward compatible, you would need to write custom function and assign INF value inside the catch block.

    <?php
    
    /**
     * Division returns INF when dividing by 0 
     * in PHP8, PHP7, PHP5
     * 
     * @param int | float $a number to divide
     * @param int | float $b number dividing by
     * 
     * @return int | float | INF
     */
    function divide($a, $b){
        try {
            if(@($a / $b) === false) return INF; // covers PHP5
            return @($a / $b); // covers PHP7
        } catch (DivisionByZeroError $e) {
            return INF; // covers PHP8
        }
    }
    
    /* Compatible with PHP8, PHP7, PHP5 */
    divide(8,2); // returns int(4)
    divide(8,1.1); // returns float(7.2727272727273)
    divide(8,0); // returns INF