Maison >développement back-end >tutoriel php >Comment créer une calculatrice PHP à l'aide de l'algorithme Shunting-Yard ?

Comment créer une calculatrice PHP à l'aide de l'algorithme Shunting-Yard ?

DDD
DDDoriginal
2024-12-07 18:52:16813parcourir

How to Build a PHP Calculator Using the Shunting-Yard Algorithm?

Comment créer une calculatrice en PHP

Problème :

Créer une calculatrice PHP capable d'évaluer les expressions algébriques simples saisies par les utilisateurs en notation algébrique standard, y compris les expressions avec parenthèses.

Approche courante :

Une solution inefficace mais temporaire consiste à remplacer des expressions dans une représentation sous forme de chaîne de l'expression, telle que :

for ($a=1; $a < 1000; $a++) {
    for ($b=1; $b < 1000; $b++) {
        string_replace($a . '*' . $b, $a*$b, $string);
    }
}

Algorithme de triage :

Une approche plus efficace consiste à utiliser l'algorithme de triage Algorithme Yard.

Implémentation :

Expressions terminales (valeurs et opérateurs) :

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;
    }
}

Pile Mise en œuvre :

class Stack {
    protected $data = [];
    public function push($element) {
        array_push($this->data, $element);
    }
    public function pop() {
        return array_pop($this->data);
    }
}

Cours de mathématiques (Exécuteur) :

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()) &amp;&amp; $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()) &amp;&amp; $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;
    }

    // ...
}

En utilisant cette implémentation, vous pouvez évaluer les expressions comme suit :

$math = new Math();
$answer = $math->evaluate('(2 + 3) * 4'); // 20
$answer = $math->evaluate('1 + 2 * ((3 + 4) * 5 + 6)'); // 83
$answer = $math->evaluate('(1 + 2) * (3 + 4) * (5 + 6)'); // 231
$math->registerVariable('a', 4);
$answer = $math->evaluate('($a + 3) * 4'); // 28

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn