PHP, How to catch a division by zero?

2019-01-01 16:32发布

I have a large mathematical expression that has to be created dynamically. For example, once I have parsed "something" the result will be a string like: "$foo+$bar/$baz";.

So, for calculating the result of that expression I'm using the eval function... something like this:

eval("\$result = $expresion;");
echo "The result is: $result";

The problem here is that sometimes I get errors that says there was a division by zero, and I don't know how to catch that Exception. I have tried things like:

eval("try{\$result = $expresion;}catch(Exception \$e){\$result = 0;}");
echo "The result is: $result";

Or:

try{
    eval("\$result = $expresion;");
}
catch(Exception $e){
    $result = 0;
}
echo "The result is: $result";

But it does not work. So, how can I avoid that my application crashes when there is a division by zero?

Edit:

First, I want to clarify something: the expression is built dynamically, so I can't just eval if the denominator is zero. So... with regards to the Mark Baker's comment, let me give you an example. My parser could build something like this:

"$foo + $bar * ( $baz / ( $foz - $bak ) )"

The parser build the string step by step without worrying about the value of the vars... so in this case if $foz == $bak there's in fact a division by zero: $baz / ( 0 ).

On the other hand as Pete suggested, I tried:

<?php
$a = 5;
$b = 0;

if(@eval(" try{ \$res = $a/$b; } catch(Exception \$e){}") === FALSE)
        $res = 0;
echo "$res\n";
?> 

But it does not print anything.

13条回答
初与友歌
2楼-- · 2019-01-01 16:35

On PHP7 you can use DivisionByZeroError

try {
    echo 1/0;
}
catch(DivisionByZeroError $e){
    echo "got $e";
}
查看更多
弹指情弦暗扣
3楼-- · 2019-01-01 16:35

Use a @ (An error control operator.) This tells php to not output warnings in case of errors.

eval("\$result = @($expresion);");
if ($result == 0) {
    // do division by zero handling 
} else {
    // it's all good
}
查看更多
零度萤火
4楼-- · 2019-01-01 16:36

I was facing that problem as well (dynamic expressions). Idid it that way which might not be the nicest way but it works. Instead of throwing an Exception you can of course return null or false or whatever you wish. Hope this helps.

function eval_expression($expression)
{
    ob_start();
    eval('echo (' .  $expression . ');');
    $result = ob_get_contents();
    ob_end_clean();
    if (strpos($result, 'Warning: Division by zero')!==false)
    {
        throw new Exception('Division by zero');
    }
    else return (float)$result;
}
查看更多
爱死公子算了
5楼-- · 2019-01-01 16:37

You just need to set an error handler to throw an exception in case of errors:

set_error_handler(function () {
    throw new Exception('Ach!');
});

try {
    $result = 4 / 0;
} catch( Exception $e ){
    echo "Divide by zero, I don't fear you!".PHP_EOL;
    $result = 0;
}

restore_error_handler();
查看更多
弹指情弦暗扣
6楼-- · 2019-01-01 16:39

You can simply catch DivisionByZeroError in PHP >= 7

See http://php.net/manual/en/class.divisionbyzeroerror.php

查看更多
美炸的是我
7楼-- · 2019-01-01 16:42
if ($baz == 0.0) {
    echo 'Divisor is 0';
} else {
    ...
}

Rather than use eval, which is highly dangerous if you're using user-input within the evalled expression, why not use a proper parser such as evalmath on PHPClasses, and which raises a clean exception on divide by zero

查看更多
登录 后发表回答