2009-11-26 3 views
2

Мне нужен способ принятия уравнения, заданного в виде строки, и нахождения математического ответа. Большое предостережение состоит в том, что я не могу использовать eval().Найти ответ на строковое уравнение без использования eval()

Я знаю, что уравнение будет содержать только числа, четыре математических оператора (т. Е. */+ -) и круглые скобки, оно может содержать или не содержать пробелы в строке. Вот несколько примеров.

4 * 4 
4+6/3 
(3/2)*(4+8) 
(4+8) * 2 

Я предполагаю, что это должно быть сделано с каким-то регулярным выражением?

+0

оценивающих строки формул довольно легко, когда они так просто, как это. См. Полдюжины ответов на http://stackoverflow.com/questions/1384811/code-golf-mathematics-expression-evaluator-full-pemdas –

ответ

9

Математические выражения не являются регулярными. Это context-free.

Ваш лучший выбор - проанализировать их с помощью известных алгоритмов синтаксического анализа, таких как . Все, о чем вам нужно беспокоиться, - это реализовать алгоритм в PHP. Возможно, вы даже сможете найти его в Интернете.

+1

Удивительно, сколько можно узнать, просто прочитав ответы на вопросы! Это ново для меня, круто! +1 – Ben

+1

Это даст вам начало: '$ tokens = token_get_all ('

4

Только в случае, если кто-то заинтересован здесь алгоритм я придумал в PHP для получения обратной польской нотации

function convertToRPN($equation) 

{ 
    $equation = str_replace(' ', '', $equation); 
    $tokens = token_get_all('<?php ' . $equation); 
    $operators = array('*' => 1, '/' => 1, '+' => 2, '-' => 2); 
    $rpn = ''; 
    $stack = array(); 
    $size = count($tokens);             
    for($i = 1; $i < $size; $i++) { 
     if(is_array($tokens[$i])) { 
      $rpn .= $tokens[$i][1] . ' '; 
     } else { 
      if(empty($stack) || $tokens[$i] == '(') { 
       $stack[] = $tokens[$i]; 
      } else { 
       if($tokens[$i] == ')') { 
        while(end($stack) != '(') { 
         $rpn .= array_pop($stack); 
        } 
        array_pop($stack); 
       } else { 
        while(!empty($stack) && end($stack) != '(' && $operators[$tokens[$i]] >= $operators[end($stack)]) { 
         $rpn .= array_pop($stack); 
        } 
        $stack[] = $tokens[$i]; 
       } 
      } 
     } 
    } 

    while(!empty($stack)) { 
     $rpn .= array_pop($stack); 
    } 

    return $rpn; 
}