PHP,如何捕捉除以零?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3071067/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 08:37:05  来源:igfitidea点击:

PHP, How to catch a division by zero?

phpexceptiondivide-by-zero

提问by Cristian

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";.

我有一个必须动态创建的大型数学表达式。例如,一旦我已经解析了“东西”,结果就会像一个字符串:"$foo+$bar/$baz";

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

因此,为了计算该表达式的结果,我正在使用该eval函数......像这样:

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 == $bakthere's in fact a division by zero: $baz / ( 0 ).

解析器逐步构建字符串而不用担心 vars 的值......所以在这种情况下,如果$foz == $bak实际上被零除:$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.

但它不打印任何东西。

采纳答案by Mark Baker

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

而不是使用 eval,如果您在 evalled 表达式中使用用户输入,这是非常危险的,为什么不使用适当的解析器,例如PHPClasses 上的 evalmath,并且在除以零时引发干净的异常

回答by tacone

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();

回答by Bill Karwin

Here's another solution:

这是另一个解决方案:

<?php

function e($errno, $errstr, $errfile, $errline) {
    print "caught!\n";
}

set_error_handler('e');

eval('echo 1/0;');

See set_error_handler()

set_error_handler()

回答by David L

On PHP7 you can use DivisionByZeroError

在 PHP7 上你可以使用DivisionByZeroError

try {
    echo 1/0;
} catch(DivisionByZeroError $e){
    echo "got $e";
} catch(ErrorException $e) {
    echo "got $e";
}

回答by Alan Storm

As others have mentioned, consider trying a solution that will let you check if the denominator is 0.

正如其他人所提到的,请考虑尝试一种解决方案,让您检查分母是否为 0。

Since that advice seems useless your purpose, here's a little background on PHP error handling.

由于该建议似乎对您的目的毫无用处,因此这里有一些 PHP 错误处理的背景知识。

Early versions of PHP didn't have exceptions. Instead, error messages of various levels were raised (Notices, Warnings, Etc). A Fatal error stops execution.

PHP 的早期版本没有例外。相反,会引发各种级别的错误消息(通知、警告等)。致命错误会停止执行。

PHP5 brought exceptions to the table, and newer PHP provided libraries (PDO) will throw exceptions when bad/unexpected things happen. Hoever, the core codebase was NOT rewritten to use exception. Core functions and operations still rely on the old error system.

PHP5 带来了异常,而较新的 PHP 提供的库 (PDO) 将在发生坏事/意外事件时抛出异常。然而,核心代码库并未重写为使用异常。核心功能和操作仍然依赖于旧的错误系统。

When you divide by 0, you get a Warning, not an exception

当您除以 0 时,您会收到警告,而不是异常

PHP Warning:  Division by zero in /foo/baz/bar/test.php(2) : eval()'d code on line 1
PHP Stack trace:
PHP   1. {main}() /foo/baz/bar/test.php:0
PHP   2. eval() /foo/baz/bar/test.php:2

If you want to "catch" these, you'll need to set a custom error handlerthat will detect division by zero errors and do something about them. Unfortunately, custom error handlers are a catch all, which means you'll also need to write some code to do something appropriate with all other errors.

如果你想“捕捉”这些,你需要设置一个自定义错误处理程序,它将检测除以零错误并对其做一些事情。不幸的是,自定义错误处理程序包罗万象,这意味着您还需要编写一些代码来处理所有其他错误。

回答by Christopher Fox

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.

我也面临这个问题(动态表达式)。这样做可能不是最好的方式,但它有效。您当然可以返回 null 或 false 或任何您想要的,而不是抛出异常。希望这可以帮助。

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;
}

回答by Pete

if(@eval("$result = $expresion;")===FALSE){
  $result=0;
}

Won't just catch divide by 0 errors though.

不过,不会只捕获除以 0 的错误。

回答by dinesh

A string containing numbers and the mathematical operators + - * / is passed as input. The program must evaluate the value of the expression (as per BODMAS) and print the output.

包含数字和数学运算符 + - * / 的字符串作为输入传递。程序必须计算表达式的值(根据 BODMAS)并打印输出。

Example Input/Output: If the argument is "7 + 4*5" the output must be 27. If the argument is "55 + 21 * 11 - 6/0" the output must be "error" (As division by zero is not defined).

示例输入/输出:如果参数是“7 + 4*5”,则输出必须是 27。如果参数是“55 + 21 * 11 - 6/0”,则输出必须是“错误”(因为除以零是没有定义的)。

回答by user3557421

Problem:

问题:

b=1; c=0; a=b/c; // Error Divide by zero

b=1; c=0; a=b/c; // Error Divide by zero

Solution simple:

解决方法简单:

if(c!=0) a=b/c;
else // error handling

回答by justin.m.chase

I've been struggling with this too, the set_error_handlersolutions were not working for me, probably based on PHP version differences.

我也一直在努力解决这个问题,set_error_handler解决方案对我不起作用,可能是基于 PHP 版本的差异。

The solution for me was to attempt to detect an error on shutdown:

我的解决方案是尝试在关机时检测错误:

// Since set_error_handler doesn't catch Fatal errors, we do this
function shutdown()
{
    $lastError = error_get_last();
    if (!empty($lastError)) {
        $GLOBALS['logger']->debug(null, $lastError);
    }
}
register_shutdown_function('shutdown');

I'm not sure why a divide by 0 is shutting down rather than being handled by the set_error_handlerbut this helped me get beyond it just silently dying.

我不确定为什么除以 0 是关闭而不是被处理,set_error_handler但这帮助我超越了它,只是默默地死去。