복붙노트

"2-1"과 같은 문자열을 수학적으로 평가하여 "1"을 생성하는 방법은 무엇입니까?

PHP

"2-1"과 같은 문자열을 수학적으로 평가하여 "1"을 생성하는 방법은 무엇입니까?

나는 PHP가 2-1과 같은 문자열을 가져 와서 그것의 산술 결과를 생성 할 수있는 함수를 가지고 있는지 궁금한가요?

또는 산술 연산자의 왼쪽과 오른쪽 값을 가져 오기 위해 explode ()를 사용하여 수동으로이 작업을 수행해야합니까?

해결법

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

    1.나는이 질문이 오래되었다는 것을 알고 있지만, 어젯밤에 꽤 관련이없는 것을 찾아 다녔다. 그리고 모든 대답은 나쁘다. 뿐만 아니라 나쁜, 아주 나쁘다. 내가 여기에 제시 한 예제는 2005 년에 만들었던 수업에서 나왔고 지난 몇 시간 동안이 질문 때문에 PHP5로 업데이트했습니다. 다른 시스템이 존재하고이 질문이 게시되기 전에 있었기 때문에 PHP의주의가 eval을 사용하는 이유는 무엇입니까?

    나는이 질문이 오래되었다는 것을 알고 있지만, 어젯밤에 꽤 관련이없는 것을 찾아 다녔다. 그리고 모든 대답은 나쁘다. 뿐만 아니라 나쁜, 아주 나쁘다. 내가 여기에 제시 한 예제는 2005 년에 만들었던 수업에서 나왔고 지난 몇 시간 동안이 질문 때문에 PHP5로 업데이트했습니다. 다른 시스템이 존재하고이 질문이 게시되기 전에 있었기 때문에 PHP의주의가 eval을 사용하는 이유는 무엇입니까?

    예제로 들어가기 전에 내가 사용할 클래스를 가져올 곳은 PHPClasses 또는 GitHub 중 하나입니다. eos.class.php와 stack.class.php는 모두 필요하지만 동일한 파일에 결합 될 수 있습니다.

    이런 종류의 클래스를 사용하는 이유는 RPN (Resin to Postfix) 파서를 포함하고 RPN Solver를 포함하기 때문입니다. 이것들을 사용하면 eval 함수를 사용하지 않고 시스템을 취약점에 노출시킬 필요가 없습니다. 수업을 받으면 2-1과 같은 간단한 (더 복잡한) 방정식을 풀 때 필요한 코드는 모두 다음과 같습니다.

    require_once "eos.class.php";
    $equation = "2-1";
    $eq = new eqEOS();
    $result = $eq->solveIF($equation);
    

    그게 다야! 대부분의 방정식에서는 이와 같은 구문 분석기를 사용할 수 있지만 "악의적 인 평가"에 의지하지 않고 복잡하고 중첩되어 있습니다.

    왜냐하면 저는이 수업에만 수업을 갖기를 원하지 않기 때문에 다른 옵션이 있습니다. 나는 8 년 동안 그것을 사용해 왔기 때문에 나는 내 자신의 것에 익숙하다. ^^

    Wolfram | 알파 API 세이지 꽤 나쁜 파서 phpdicecalc

    내가 이전에 찾은 다른 사람에게 무슨 일이 일어 났는지에 대해서는 잘 모르겠지만 이전에는 GitHub에서 또 다른 문제가 발생했습니다. 불행히도 북마크하지는 않았지만 파서도 포함 된 대규모 플로트 작업과 관련이 있습니다.

    어쨌든, PHP에서 방정식을 푸는 것에 대한 해답이 앞으로 Google 검색의 최상위에 올랐기 때문에 모든 미래의 검색 사용자를 평가하지 않았 음을 확인하고 싶습니다. ^^

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

    2.

    $operation='2-1';
    eval("\$value = \"$operation\";");
    

    또는

    $value=eval("return ($op);");
    
  3. ==============================

    3.이것은 eval이 유용하게 사용되는 경우 중 하나입니다.

    이것은 eval이 유용하게 사용되는 경우 중 하나입니다.

    $expression = '2 - 1';
    eval( '$result = (' . $expression . ');' );
    echo $result;
    
  4. ==============================

    4.BC Math를 임의의 정밀도로 사용할 수 있습니다.

    BC Math를 임의의 정밀도로 사용할 수 있습니다.

    echo bcsub(5, 4); // 1
    echo bcsub(1.234, 5); // 3
    echo bcsub(1.234, 5, 4); // -3.7660
    

    http://www.php.net/manual/en/function.bcsub.php

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

    5.이 포럼에서 누군가가 평가없이 그것을 만들었습니다. 어쩌면 시도해 볼 수 있을까요? 그 (것)들에 신용, 나는 지금 막 그것을 찾아 냈다.

    이 포럼에서 누군가가 평가없이 그것을 만들었습니다. 어쩌면 시도해 볼 수 있을까요? 그 (것)들에 신용, 나는 지금 막 그것을 찾아 냈다.

    function calculate_string( $mathString )    {
        $mathString = trim($mathString);     // trim white spaces
        $mathString = ereg_replace ('[^0-9\+-\*\/\(\) ]', '', $mathString);    // remove any non-numbers chars; exception for math operators
    
        $compute = create_function("", "return (" . $mathString . ");" );
        return 0 + $compute();
    }
    
    $string = " (1 + 1) * (2 + 2)";
    echo calculate_string($string);  // outputs 8  
    
  6. ==============================

    6.또한이 답변을 참조하십시오 : 간단한 수학 표현의 문자열 평가

    또한이 답변을 참조하십시오 : 간단한 수학 표현의 문자열 평가

    이 솔루션은 BODMAS를 따르지 않지만 평가 문자열에서 대괄호를 사용하여이를 극복 할 수 있습니다.

    function callback1($m) {
        return string_to_math($m[1]);
    }
    function callback2($n,$m) {
        $o=$m[0];
        $m[0]=' ';
        return $o=='+' ? $n+$m : ($o=='-' ? $n-$m : ($o=='*' ? $n*$m : $n/$m));
    }
    function string_to_math($s){ 
        while ($s != ($t = preg_replace_callback('/\(([^()]*)\)/','callback1',$s))) $s=$t;
        preg_match_all('![-+/*].*?[\d.]+!', "+$s", $m);
        return array_reduce($m[0], 'callback2');
    }
    echo string_to_match('2-1'); //returns 1
    
  7. ==============================

    7.여기에 약간 다른 코드가 있습니다. eval ()이없는 BOMDAS를 따르지 만 복합 / 상위 순서 / 괄호 식을 수행 할 수있는 기능이 없습니다. 이 라이브러리가 필요없는 접근 방식은 표현식을 분리하고 모든 연산자가 제거 될 때까지 구성 요소의 배열을 체계적으로 줄입니다. 그것은 확실히 당신의 표정 표현을 위해 작동합니다 : 2-1;)

    여기에 약간 다른 코드가 있습니다. eval ()이없는 BOMDAS를 따르지 만 복합 / 상위 순서 / 괄호 식을 수행 할 수있는 기능이 없습니다. 이 라이브러리가 필요없는 접근 방식은 표현식을 분리하고 모든 연산자가 제거 될 때까지 구성 요소의 배열을 체계적으로 줄입니다. 그것은 확실히 당신의 표정 표현을 위해 작동합니다 : 2-1;)

    ** 음수를 허용하도록 업데이트 **

    이에 : (하지만)

    $expression="-11+3*1*4/-6-12";
    if(!preg_match('~^-?\d*\.?\d+([*/+-]-?\d*\.?\d+)*$~',$expression)){
        echo "invalid expression";
    }else{
        $components=preg_split('~(?<=\d)([*/+-])~',$expression,NULL,PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
        var_export($components);  // ['-11','+','3','*','1','*','4','/','-6','-','12']
        while(($index=array_search('*',$components))!==false){
            array_splice($components,$index-1,3,$components[$index-1]*$components[$index+1]);
            var_export($components);
            // ['-11','+','3','*','4','/','-6','-','12']
            // ['-11','+','12','/','-6','-','12']
        }
        while(($index=array_search('/',$components))!==false){
            array_splice($components,$index-1,3,$components[$index-1]/$components[$index+1]);
            var_export($components);  // [-'11','+','-2','-','12']
        }
        while(($index=array_search('+',$components))!==false){
            array_splice($components,$index-1,3,$components[$index-1]+$components[$index+1]);
            var_export($components);  // ['-13','-','12']
        }
        while(($index=array_search('-',$components))!==false){
            array_splice($components,$index-1,3,$components[$index-1]-$components[$index+1]);
            var_export($components); // [-25]
        }
        echo current($components);  // -25
    }
    

    다음은 두 숫자 (양수 또는 음수) 사이에 ^가있을 때 php의 pow ()를 사용하는 BOMDAS 버전의 데모입니다.

    나는 괄호 안의 표현을 다루는 버전을 쓰는 것을 괴롭히지 않을 것이라고 생각하지만 ... 나는 지루해하는 것을 보게 될 것이다.

  8. from https://stackoverflow.com/questions/5057320/how-to-mathematically-evaluate-a-string-like-2-1-to-produce-1 by cc-by-sa and MIT license