問題:
入力された単純な代数式を評価できる PHP 電卓を作成するユーザーによる標準代数表記 (次の式を含む)
一般的なアプローチ:
非効率的ではあるが一時的な解決策には、次のような式の文字列表現内の式を置き換えることが含まれます。 >
操車場アルゴリズム:for ($a=1; $a < 1000; $a++) { for ($b=1; $b < 1000; $b++) { string_replace($a . '*' . $b, $a*$b, $string); } }
より効率的なアプローチは、操車場アルゴリズムを使用することです。
実装:
ターミナル式 (値)そして演算子):
スタック実装:
abstract class TerminalExpression { protected $value = ''; public static function factory($value) { // Create terminal expressions based on the provided value (number, operator, or parenthesis) } abstract public function operate(Stack $stack); } class Number extends TerminalExpression { public function operate(Stack $stack) { return $this->value; } } class Operator extends TerminalExpression { protected $precidence = 0; protected $leftAssoc = true; public function getPrecidence() { return $this->precidence; } public function isLeftAssoc() { return $this->leftAssoc; } } class Addition extends Operator { protected $precidence = 4; } class Subtraction extends Operator { protected $precidence = 4; } class Multiplication extends Operator { protected $precidence = 5; } class Division extends Operator { protected $precidence = 5; } class Parenthesis extends TerminalExpression { protected $precidence = 7; public function isParenthesis() { return true; } }
数学クラス (実行者):
class Stack { protected $data = []; public function push($element) { array_push($this->data, $element); } public function pop() { return array_pop($this->data); } }
この実装を使用すると、式を次のように評価できます。以下:
class Math { protected $variables = []; public function evaluate($string) { $stack = $this->parse($string); return $this->run($stack); } public function parse($string) { // Tokenize expression $tokens = array_map('trim', preg_split('((\d+|\+|-|\(|\)|\*|/)|\s+)', $string, null, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE)); // Parse operators and parentheses using the Shunting Yard algorithm $output = new Stack(); $operators = new Stack(); foreach ($tokens as $token) { $expression = TerminalExpression::factory($token); if ($expression->isOperator()) { $this->parseOperator($expression, $output, $operators); } elseif ($expression->isParenthesis()) { $this->parseParenthesis($expression, $output, $operators); } else { $output->push($expression); } } // Pop remaining operators on stack and push to output while (($op = $operators->pop()) && $op->isOperator()) { if ($op->isParenthesis()) { throw new RuntimeException('Mismatched Parenthesis'); } $output->push($op); } return $output; } public function run(Stack $stack) { // Evaluate stack and return result while (($operator = $stack->pop()) && $operator->isOperator()) { $value = $operator->operate($stack); $stack->push(TerminalExpression::factory($value)); } return $operator ? $operator->render() : $this->render($stack); } protected function extractVariables($token) { if ($token[0] == '$') { $key = substr($token, 1); return isset($this->variables[$key]) ? $this->variables[$key] : 0; } return $token; } // ... }
以上が操車場アルゴリズムを使用して PHP 計算機を構築するには?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。