亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

Table of Contents
2. Parsing with Shunting Yard Algorithm (Convert to RPN)
3. Evaluating the RPN Expression
4. Putting It All Together
5. Usage Example
Key Features & Benefits
Possible Enhancements
Home Backend Development PHP Tutorial Implementing a Custom Mathematical Expression Parser and Evaluator in PHP

Implementing a Custom Mathematical Expression Parser and Evaluator in PHP

Jul 31, 2025 pm 12:43 PM
PHP Math

答案是:通過分步實(shí)現(xiàn)詞法分析、Shunting Yard算法解析和RPN求值,可構(gòu)建安全可控的PHP數(shù)學(xué)表達(dá)式求值器。1. tokenize函數(shù)將輸入拆分為數(shù)字、變量、操作符等標(biāo)記;2. parseToRPN使用Shunting Yard算法按優(yōu)先級(jí)和結(jié)合性轉(zhuǎn)換為逆波蘭表示;3. evaluateRPN利用棧結(jié)構(gòu)結(jié)合變量上下文計(jì)算結(jié)果;4. evaluateExpression整合流程并處理異常;5. 示例顯示支持變量和標(biāo)準(zhǔn)運(yùn)算,具備安全性、可擴(kuò)展性與錯(cuò)誤處理能力,適用于需避免eval()風(fēng)險(xiǎn)的場(chǎng)景。

Implementing a Custom Mathematical Expression Parser and Evaluator in PHP

Creating a custom mathematical expression parser and evaluator in PHP can be useful when you need more control than eval() provides—especially for security, extensibility, or educational purposes. While eval() can execute expressions, it's dangerous with untrusted input and lacks flexibility. Building your own parser allows you to safely evaluate expressions like 2 + 3 * (4 - 1) while supporting variables, functions, and error handling.

Implementing a Custom Mathematical Expression Parser and Evaluator in PHP

Here’s how to implement a simple yet effective mathematical expression parser and evaluator in PHP.


1. Tokenization: Breaking the Input into Meaningful Parts

The first step is to convert the input string into tokens—numbers, operators, parentheses, variables, and functions.

Implementing a Custom Mathematical Expression Parser and Evaluator in PHP
function tokenize($expression) {
    $tokens = [];
    $length = strlen($expression);
    $i = 0;

    while ($i < $length) {
        $char = $expression[$i];

        if (ctype_digit($char) || $char === '.') {
            $num = '';
            while ($i < $length && (ctype_digit($expression[$i]) || $expression[$i] === '.')) {
                $num .= $expression[$i++];
            }
            $tokens[] = ['type' => 'number', 'value' => (float)$num];
            $i--;
        } elseif (ctype_alpha($char)) {
            $var = '';
            while ($i < $length && ctype_alnum($expression[$i])) {
                $var .= $expression[$i++];
            }
            $tokens[] = ['type' => 'variable', 'value' => $var];
            $i--;
        } elseif (in_array($char, ['+', '-', '*', '/', '^', '(', ')'])) {
            $tokens[] = ['type' => 'operator', 'value' => $char];
        } elseif ($char === ' ') {
            // Skip whitespace
        } else {
            throw new Exception("Unknown character: $char");
        }
        $i++;
    }

    return $tokens;
}

This tokenizer handles numbers (including decimals), variables (like x, y1), operators, and parentheses.


2. Parsing with Shunting Yard Algorithm (Convert to RPN)

We’ll use the Shunting Yard algorithm by Edsger Dijkstra to convert infix notation (standard math) to Reverse Polish Notation (RPN), which is easier to evaluate.

Implementing a Custom Mathematical Expression Parser and Evaluator in PHP
function parseToRPN($tokens) {
    $output = [];
    $operators = [];
    $precedence = ['+' => 1, '-' => 1, '*' => 2, '/' => 2, '^' => 3];
    $associativity = ['+' => 'left', '-' => 'left', '*' => 'left', '/' => 'left', '^' => 'right'];

    foreach ($tokens as $token) {
        if ($token['type'] === 'number' || $token['type'] === 'variable') {
            $output[] = $token;
        } elseif ($token['value'] === '(') {
            $operators[] = $token;
        } elseif ($token['value'] === ')') {
            while (!empty($operators) && end($operators)['value'] !== '(') {
                $output[] = array_pop($operators);
            }
            array_pop($operators); // Remove '('
        } elseif ($token['type'] === 'operator') {
            $op = $token['value'];
            while (
                !empty($operators) &&
                ($top = end($operators))['value'] !== '(' &&
                isset($precedence[$top['value']]) &&
                (
                    ($associativity[$op] === 'left' && $precedence[$op] <= $precedence[$top['value']]) ||
                    ($associativity[$op] === 'right' && $precedence[$op] < $precedence[$top['value']])
                )
            ) {
                $output[] = array_pop($operators);
            }
            $operators[] = $token;
        }
    }

    while (!empty($operators)) {
        $output[] = array_pop($operators);
    }

    return $output;
}

This algorithm respects operator precedence and associativity (e.g., ^ is right-associative).


3. Evaluating the RPN Expression

Now evaluate the RPN using a stack. Variables are resolved from a provided context (e.g., ['x' => 5]).

function evaluateRPN($rpn, $variables = []) {
    $stack = [];

    foreach ($rpn as $token) {
        if ($token['type'] === 'number') {
            $stack[] = $token['value'];
        } elseif ($token['type'] === 'variable') {
            if (!isset($variables[$token['value']])) {
                throw new Exception("Undefined variable: " . $token['value']);
            }
            $stack[] = $variables[$token['value']];
        } elseif ($token['type'] === 'operator') {
            if (count($stack) < 2) {
                throw new Exception("Invalid expression");
            }
            $b = array_pop($stack);
            $a = array_pop($stack);
            switch ($token['value']) {
                case '+': $stack[] = $a + $b; break;
                case '-': $stack[] = $a - $b; break;
                case '*': $stack[] = $a * $b; break;
                case '/': 
                    if ($b == 0) throw new Exception("Division by zero");
                    $stack[] = $a / $b; 
                    break;
                case '^': $stack[] = pow($a, $b); break;
                default: throw new Exception("Unknown operator: " . $token['value']);
            }
        }
    }

    if (count($stack) !== 1) {
        throw new Exception("Invalid expression");
    }

    return $stack[0];
}

4. Putting It All Together

Now create a simple wrapper function:

function evaluateExpression($expression, $variables = []) {
    try {
        $tokens = tokenize($expression);
        $rpn = parseToRPN($tokens);
        return evaluateRPN($rpn, $variables);
    } catch (Exception $e) {
        return "Error: " . $e->getMessage();
    }
}

5. Usage Example

echo evaluateExpression("2 + 3 * (4 - 1)"); // Output: 11
echo evaluateExpression("x + y * 2", ['x' => 5, 'y' => 3]); // Output: 11
echo evaluateExpression("z ^ 2", ['z' => 4]); // Output: 16

Key Features & Benefits

  • Safe: No use of eval(), so no code injection.
  • Extensible: You can add functions (e.g., sin, sqrt) by extending the tokenizer and evaluator.
  • Error Handling: Clear messages for undefined variables, syntax issues, or division by zero.
  • Supports Variables: Useful for dynamic expressions in forms, calculators, or rule engines.

Possible Enhancements

  • Support for built-in math functions (e.g., sin(x)).
  • Unary operators (e.g., -5, +3).
  • Better error recovery and syntax validation.
  • Custom operator definitions.

Building your own parser gives deep insight into how programming languages and calculators work. While tools like eval() or external libraries exist, a custom parser offers control, safety, and learning value.

Basically, it's not complex once you break it down—tokenize, parse, evaluate.

The above is the detailed content of Implementing a Custom Mathematical Expression Parser and Evaluator in PHP. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undress AI Tool

Undress AI Tool

Undress images for free

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Navigating the Pitfalls of Floating-Point Inaccuracy in PHP Navigating the Pitfalls of Floating-Point Inaccuracy in PHP Jul 29, 2025 am 05:01 AM

Floating point numbers are inaccurate is a common problem in PHP. The answer is that it uses IEEE754 double-precision format, which makes decimal decimals unable to be accurately represented; numbers such as 1.0.1 or 0.2 are infinite loop decimals in binary, and the computer needs to truncate them to cause errors; 2. When comparing floating point numbers, you should use tolerance instead of ==, such as abs($a-$b)

The Nuances of Numerical Precision: `round()`, `ceil()`, and `floor()` Pitfalls The Nuances of Numerical Precision: `round()`, `ceil()`, and `floor()` Pitfalls Jul 29, 2025 am 04:55 AM

round()uses"roundhalftoeven",not"roundhalfup",soround(2.5)returns2andround(3.5)returns4tominimizestatisticalbias,whichmaysurprisethoseexpectingtraditionalrounding.2.Floating-pointrepresentationerrorscausenumberslike2.675tobestored

Handling Cryptocurrency Calculations: Why BCMath is Essential in PHP Handling Cryptocurrency Calculations: Why BCMath is Essential in PHP Aug 01, 2025 am 07:48 AM

BCMathisessentialforaccuratecryptocurrencycalculationsinPHPbecausefloating-pointarithmeticintroducesunacceptableroundingerrors.1.Floating-pointnumberslike0.1 0.2yieldimpreciseresults(e.g.,0.30000000000000004),whichisproblematicincryptowhereprecisionu

Fundamentals of Vector Mathematics for 2D/3D Graphics in PHP Fundamentals of Vector Mathematics for 2D/3D Graphics in PHP Jul 29, 2025 am 04:25 AM

AvectorinPHPgraphicsrepresentsposition,direction,orvelocityusingaclasslikeVector3Dwithx,y,zcomponents.2.Basicoperationsincludeaddition,subtraction,scalarmultiplication,anddivisionformovementandscaling.3.MagnitudeiscalculatedviathePythagoreantheorem,a

The Role of Modular Arithmetic in PHP for Cryptographic Applications The Role of Modular Arithmetic in PHP for Cryptographic Applications Jul 30, 2025 am 12:17 AM

ModulararithmeticisessentialinPHPcryptographicapplicationsdespitePHPnotbeingahigh-performancelanguage;2.Itunderpinspublic-keysystemslikeRSAandDiffie-Hellmanthroughoperationssuchasmodularexponentiationandinverses;3.PHP’snative%operatorfailswithlargecr

Building a Statistical Analysis Toolkit: Mean, Median, and Standard Deviation in PHP Building a Statistical Analysis Toolkit: Mean, Median, and Standard Deviation in PHP Jul 30, 2025 am 05:17 AM

Calculate the mean: Use array_sum() to divide by the number of elements to get the mean; 2. Calculate the median: After sorting, take the intermediate value, and take the average of the two intermediate numbers when there are even elements; 3. Calculate the standard deviation: first find the mean, then calculate the average of the squared difference between each value and the mean (the sample is n-1), and finally take the square root; by encapsulating these three functions, basic statistical tools can be constructed, suitable for the analysis of small and medium-sized data, and pay attention to processing empty arrays and non-numerical inputs, and finally realize the core statistical features of the data without relying on external libraries.

Accelerating Large Number Arithmetic: A Deep Dive into PHP's GMP Extension Accelerating Large Number Arithmetic: A Deep Dive into PHP's GMP Extension Jul 29, 2025 am 04:53 AM

GMPisessentialforhandlinglargeintegersinPHPbeyondnativelimits.1.GMPenablesarbitrary-precisionintegerarithmeticusingoptimizedClibraries,unlikenativeintegersthatoverfloworBCMaththatisslowerandstring-based.2.UseGMPforheavyintegeroperationslikefactorials

Mastering Number Systems: Advanced Base Conversion Techniques in PHP Mastering Number Systems: Advanced Base Conversion Techniques in PHP Jul 30, 2025 am 02:33 AM

To improve the binary conversion capabilities in PHP, you must first implement custom binary conversion functions to support more than 36% of the digits and custom character sets. 1. Use toBase and fromBase functions combined with custom digits arrays to realize arbitrary binary conversion; 2. When processing large numbers, you should use the bccomp, bcmod and bcdiv functions extended by BCMath to ensure accuracy; 3. Build the BaseEncoder class to implement bidirectional security mapping to ensure reversible encoding and decoding; 4. Always verify the input and unify the character order; 5. Avoid using base_convert to handle large numbers, and prioritize GMP to improve performance, and ultimately realize a robust and extensible binary conversion system.

See all articles