У меня есть большое математическое выражение, которое должно быть создано динамично. Например, после того как я проанализировал "что-то", как что результатом будет строка: "$foo+$bar/$baz";
.
Так, для вычисления результата того выражения я использую eval
функционируйте... что-то вроде этого:
eval("\$result = $expresion;");
echo "The result is: $result";
Проблема здесь состоит в том, что иногда я получаю ошибки, который говорит, что было деление на нуль, и я не знаю, как поймать то Исключение. Я попробовал вещи как:
eval("try{\$result = $expresion;}catch(Exception \$e){\$result = 0;}");
echo "The result is: $result";
Или:
try{
eval("\$result = $expresion;");
}
catch(Exception $e){
$result = 0;
}
echo "The result is: $result";
Но это не работает. Так, как я могу избежать, что мои сбои приложения, когда существует деление на нуль?
Править:
Во-первых, я хочу разъяснить что-то: выражение создается динамично, таким образом, я не могу просто оценка, если знаменатель является нулем. Так... относительно комментария Mark Baker, позвольте мне дать Вам пример. Мой синтаксический анализатор мог создать что-то вроде этого:
"$foo + $bar * ( $baz / ( $foz - $bak ) )"
Сборка синтаксического анализатора строка шаг за шагом, не вызывая беспокойство о значении Вара... так в этом случае, если $foz == $bak
существует на самом деле деление на нуль: $baz / ( 0 )
.
С другой стороны, как предложенный Pete, я попробовал:
<?php
$a = 5;
$b = 0;
if(@eval(" try{ \$res = $a/$b; } catch(Exception \$e){}") === FALSE)
$res = 0;
echo "$res\n";
?>
Но это ничего не печатает.
if ($baz == 0.0) {
echo 'Divisor is 0';
} else {
...
}
Вместо того, чтобы использовать eval, что очень опасно, если вы используете вводимые пользователем данные в названном выражении, почему бы не использовать правильный синтаксический анализатор, такой как evalmath на PHPClasses , который вызывает чистое исключение на разделить на ноль
Вот еще одно решение:
<?php
function e($errno, $errstr, $errfile, $errline) {
print "caught!\n";
}
set_error_handler('e');
eval('echo 1/0;');
if(@eval("\$result = $expresion;")===FALSE){
$result=0;
}
Но не будет просто уловить ошибки деления на 0.
Используйте @
(оператор контроля ошибок.) Это говорит php не выводить предупреждения в случае ошибок.
eval("\$result = @($expresion);");
if ($result == 0) {
// do division by zero handling
} else {
// it's all good
}
Как уже упоминали другие, попробуйте решение, которое позволит вам проверить, равен ли знаменатель 0.
Поскольку этот совет кажется бесполезным для вашей цели, вот небольшая справочная информация по обработке ошибок PHP.
В ранних версиях PHP не было исключений. Вместо этого появлялись сообщения об ошибках различного уровня (Уведомления, предупреждения и т. Д.). Неустранимая ошибка останавливает выполнение.
PHP5 внес исключения в таблицу, а новые библиотеки, предоставляемые PHP (PDO), будут генерировать исключения, когда происходят плохие / неожиданные вещи. Однако основная кодовая база НЕ была переписана для использования исключения. Основные функции и операции по-прежнему полагаются на старую систему ошибок.
Когда вы делите на 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
Если вы хотите «поймать» их, вам нужно установить собственный обработчик ошибок , который будет определять деление на ноль ошибок и что-нибудь с ними делать. К сожалению, пользовательские обработчики ошибок - это уловка, а это значит, что вам также нужно написать код, чтобы делать что-то подходящее со всеми другими ошибками.
Я тоже столкнулся с этой проблемой (динамические выражения). Я так и сделал, что может быть не самым лучшим способом, но он работает. Вместо того, чтобы бросать Exception, вы, конечно, можете вернуть 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;
}