복붙노트

PHP, 0으로 나누는 방법은?

PHP

PHP, 0으로 나누는 방법은?

나는 동적으로 생성 되어야만하는 큰 수학적 표현을 가지고있다. 예를 들어, "무언가"를 파싱하면 결과는 "$ 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";

그러나 그것은 효과가 없습니다. 따라서 0으로 나눈 값이있을 때 응용 프로그램이 충돌하는 것을 어떻게 피할 수 있습니까?

편집하다:

첫째, 뭔가 명확히하고 싶습니다. 표현식이 동적으로 만들어 지므로 분모가 0이면 평가할 수 없습니다. 그래서 ... 마크 베이커의 의견에 관해서, 제가 한 가지 예를 들어 드리도록하겠습니다. 파서는 다음과 같이 작성할 수 있습니다.

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

구문 분석기는 vars의 값을 걱정하지 않고 단계별로 문자열을 작성합니다.이 경우 $ foz == $ bak 인 경우 사실 0으로 나누기 : $ baz / (0)입니다.

반면 Pete가 제안한 것처럼 나는 다음과 같이 시도했다.

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

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

그러나 아무것도 인쇄하지 않습니다.

해결법

  1. ==============================

    1.

    if ($baz == 0.0) {
        echo 'Divisor is 0';
    } else {
        ...
    }
    

    명시된 표현식 내에서 사용자 입력을 사용하는 경우 매우 위험한 eval을 사용하는 대신 PHPClasses에서 evalmath와 같은 적절한 구문 분석기를 사용하고 0으로 나누면 깨끗한 예외가 발생합니다.

  2. ==============================

    2.다른 해결책이 있습니다.

    다른 해결책이 있습니다.

    <?php
    
    function e($errno, $errstr, $errfile, $errline) {
        print "caught!\n";
    }
    
    set_error_handler('e');
    
    eval('echo 1/0;');
    

    set_error_handler ()를 참조하십시오.

  3. ==============================

    3.오류 발생시 예외를 throw하도록 오류 처리기를 설정하면됩니다.

    오류 발생시 예외를 throw하도록 오류 처리기를 설정하면됩니다.

    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();
    
  4. ==============================

    4.다른 사람들이 언급했듯이, 분모가 0인지 확인할 수있는 솔루션을 시도해보십시오.

    다른 사람들이 언급했듯이, 분모가 0인지 확인할 수있는 솔루션을 시도해보십시오.

    그 충고가 당신의 목적을 쓸모없는 것처럼 보이기 때문에 여기 PHP 오류 처리에 대한 약간의 배경이 있습니다.

    초기 PHP 버전에는 예외가 없었습니다. 대신 다양한 수준의 오류 메시지가 발생했습니다 (주의 사항, 경고 등). 치명적 오류는 실행을 중지합니다.

    PHP5는 테이블에 예외를 가져 왔고, 나쁜 / 예상치 못한 일이 발생하면 최신 PHP 제공 라이브러리 (PDO)가 예외를 throw합니다. 그러나 핵심 코드베이스는 예외를 사용하도록 재 작성되지 않았습니다. 핵심 기능과 운영은 여전히 ​​오래된 오류 시스템에 의존합니다.

    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
    

    이들을 "잡으려는 경우"0 오류로 나누기를 감지하고 그에 대한 조치를 취할 사용자 정의 오류 처리기를 설정해야합니다. 불행하게도, 커스텀 에러 핸들러는 모두 잡을 수 있습니다. 따라서 다른 모든 에러들과 적절한 것을하기위한 코드를 작성해야합니다.

  5. ==============================

    5.

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

    단지 0 오류로 나누기를 포기하지는 않습니다.

  6. ==============================

    6.나는 그 문제 (역동적 인 표현)에도 직면했다. 그것이 가장 좋은 방법이 아닐지도 모르겠지만 그런 식으로 설명해주십시오. Exception을 throw하는 대신 null 또는 false 또는 원하는 것을 반환 할 수 있습니다. 희망이 도움이됩니다.

    나는 그 문제 (역동적 인 표현)에도 직면했다. 그것이 가장 좋은 방법이 아닐지도 모르겠지만 그런 식으로 설명해주십시오. Exception을 throw하는 대신 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;
    }
    
  7. ==============================

    7.PHP7에서는 DivisionByZeroError를 사용할 수 있습니다.

    PHP7에서는 DivisionByZeroError를 사용할 수 있습니다.

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

    8.PHP> = 7에서 DivisionByZeroError를 잡을 수 있습니다.

    PHP> = 7에서 DivisionByZeroError를 잡을 수 있습니다.

    http://php.net/manual/en/class.divisionbyzeroerror.php를 참조하십시오.

  9. ==============================

    9.@ (오류 제어 연산자)를 사용하십시오. 이것은 PHP가 오류가 발생할 경우 경고를 출력하지 않도록 지시합니다.

    @ (오류 제어 연산자)를 사용하십시오. 이것은 PHP가 오류가 발생할 경우 경고를 출력하지 않도록 지시합니다.

    eval("\$result = @($expresion);");
    if ($result == 0) {
        // do division by zero handling 
    } else {
        // it's all good
    }
    
  10. ==============================

    10.숫자를 포함하는 문자열과 수학 연산자 + - * /가 입력으로 전달됩니다. 프로그램은 BODMAS에 따라 표현식의 값을 평가하고 출력을 인쇄해야합니다.

    숫자를 포함하는 문자열과 수학 연산자 + - * /가 입력으로 전달됩니다. 프로그램은 BODMAS에 따라 표현식의 값을 평가하고 출력을 인쇄해야합니다.

    입력 / 출력의 예 : 인수가 "7 + 4 * 5"이면 출력은 27이어야합니다. 인수가 "55 + 21 * 11 - 6/0"이면 출력은 "오류"(0으로 나누기가 정의되지 않음) 여야합니다.

  11. ==============================

    11.문제:

    문제:

    b = 1; c = 0; a = b / c; // 오류 0으로 나누기

    간단한 솔루션 :

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

    12.나는 이것에 대해서도 고심하고 있었고, 아마도 PHP 버전 차이에 기반하여 set_error_handler 솔루션이 나에게 도움이되지 못했다.

    나는 이것에 대해서도 고심하고 있었고, 아마도 PHP 버전 차이에 기반하여 set_error_handler 솔루션이 나에게 도움이되지 못했다.

    나를위한 해결책은 종료시 오류를 감지하려고 시도하는 것이 었습니다.

    // 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');
    

    0으로 나누는 것이 set_error_handler에 의해 처리되는 것보다 종료되는 이유를 모르겠지만, 이것이 자동으로 죽어가는 것을 넘어서게되었습니다.

  13. from https://stackoverflow.com/questions/3071067/php-how-to-catch-a-division-by-zero by cc-by-sa and MIT license