php 使用 eval 从字符串计算数学表达式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18880772/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 18:23:23  来源:igfitidea点击:

calculate math expression from a string using eval

phpmatheval

提问by Langkiller

I want to calculate math expression from a string. I have read that the solution to this is to use eval(). But when I try to run the following code:

我想从字符串计算数学表达式。我已经读过,解决这个问题的方法是使用 eval()。但是当我尝试运行以下代码时:

<?php

$ma ="2+10";
$p = eval($ma);
print $p;

?>

It gives me the following error:

它给了我以下错误:

Parse error: syntax error, unexpected $end in C:\xampp\htdocs\eclipseWorkspaceWebDev\MandatoryHandinSite\tester.php(4) : eval()'d code on line 1

解析错误:语法错误,意外的 $end in C:\xampp\htdocs\eclipseWorkspaceWebDev\MandatoryHandinSite\tester.php(4) : eval()'d code on line 1

Does someone know the solution to this problem.

有没有人知道这个问题的解决方案。

回答by Rocket Hazmat

While I don't suggest using evalfor this (it is notthe solution), the problem is that evalexpects complete lines of code, not just fragments.

虽然我不建议eval为此使用(这不是解决方案),但问题是eval需要完整的代码行,而不仅仅是片段。

$ma ="2+10";
$p = eval('return '.$ma.';');
print $p;

Should do what you want.

应该做你想做的。



A better solution would be to write a tokenizer/parser for your math expression. Here's a very simple regex-based one to give you an example:

更好的解决方案是为您的数学表达式编写分词器/解析器。这是一个非常简单的基于正则表达式的示例:

$ma = "2+10";

if(preg_match('/(\d+)(?:\s*)([\+\-\*\/])(?:\s*)(\d+)/', $ma, $matches) !== FALSE){
    $operator = $matches[2];

    switch($operator){
        case '+':
            $p = $matches[1] + $matches[3];
            break;
        case '-':
            $p = $matches[1] - $matches[3];
            break;
        case '*':
            $p = $matches[1] * $matches[3];
            break;
        case '/':
            $p = $matches[1] / $matches[3];
            break;
    }

    echo $p;
}

回答by clarkk

Take a look at this..

看看这个..

I use this in an accounting system where you can write math expressions in amount input fields..

我在会计系统中使用它,您可以在其中在金额输入字段中编写数学表达式。

Examples

例子

$Cal = new Field_calculate();

$result = $Cal->calculate('5+7'); // 12
$result = $Cal->calculate('(5+9)*5'); // 70
$result = $Cal->calculate('(10.2+0.5*(2-0.4))*2+(2.1*4)'); // 30.4

Code

代码

class Field_calculate {
    const PATTERN = '/(?:\-?\d+(?:\.?\d+)?[\+\-\*\/])+\-?\d+(?:\.?\d+)?/';

    const PARENTHESIS_DEPTH = 10;

    public function calculate($input){
        if(strpos($input, '+') != null || strpos($input, '-') != null || strpos($input, '/') != null || strpos($input, '*') != null){
            //  Remove white spaces and invalid math chars
            $input = str_replace(',', '.', $input);
            $input = preg_replace('[^0-9\.\+\-\*\/\(\)]', '', $input);

            //  Calculate each of the parenthesis from the top
            $i = 0;
            while(strpos($input, '(') || strpos($input, ')')){
                $input = preg_replace_callback('/\(([^\(\)]+)\)/', 'self::callback', $input);

                $i++;
                if($i > self::PARENTHESIS_DEPTH){
                    break;
                }
            }

            //  Calculate the result
            if(preg_match(self::PATTERN, $input, $match)){
                return $this->compute($match[0]);
            }
            // To handle the special case of expressions surrounded by global parenthesis like "(1+1)"
            if(is_numeric($input)){
                return $input;
            }

            return 0;
        }

        return $input;
    }

    private function compute($input){
        $compute = create_function('', 'return '.$input.';');

        return 0 + $compute();
    }

    private function callback($input){
        if(is_numeric($input[1])){
            return $input[1];
        }
        elseif(preg_match(self::PATTERN, $input[1], $match)){
            return $this->compute($match[0]);
        }

        return 0;
    }
}

回答by Marcodor

Using evalfunction is very dangerous when you can't control the string argument.

当您无法控制字符串参数时,使用eval函数是非常危险的。

Try Matexfor safe Mathematical formulas calculation.

尝试使用Matex进行安全的数学公式计算。

回答by DivineOmega

I recently created a PHP package that provides a math_evalhelper function. It does exactly what you need, without the need to use the potentially unsafe evalfunction.

我最近创建了一个提供math_eval辅助函数的 PHP 包。它完全满足您的需求,无需使用潜在的不安全eval功能。

You just pass in the string version of the mathematical expression and it returns the result.

您只需传入数学表达式的字符串版本,它就会返回结果。

$two   = math_eval('1 + 1');
$three = math_eval('5 - 2');
$ten   = math_eval('2 * 5');
$four  = math_eval('8 / 2');

You can also pass in variables, which will be substituted if needed.

您还可以传入变量,如果需要,这些变量将被替换。

$ten     = math_eval('a + b', ['a' => 7, 'b' => 3]);
$fifteen = math_eval('x * y', ['x' => 3, 'y' => 5]);

Link: https://github.com/langleyfoxall/math_eval

链接:https: //github.com/langleyfoxall/math_eval

回答by Gowtham Sooryaraj

Solved!

解决了!

<?php 
function evalmath($equation)
{
    $result = 0;
    // sanitize imput
    $equation = preg_replace("/[^a-z0-9+\-.*\/()%]/","",$equation);
    // convert alphabet to $variabel 
    $equation = preg_replace("/([a-z])+/i", "$
$ma ="print (2+10);";
eval($ma);
", $equation); // convert percentages to decimal $equation = preg_replace("/([+-])([0-9]{1})(%)/","*(1$1.0$2)",$equation); $equation = preg_replace("/([+-])([0-9]+)(%)/","*(1$1.$2)",$equation); $equation = preg_replace("/([0-9]{1})(%)/",".0$1",$equation); $equation = preg_replace("/([0-9]+)(%)/",".$1",$equation); if ( $equation != "" ){ $result = @eval("return " . $equation . ";" ); } if ($result == null) { throw new Exception("Unable to calculate equation"); } echo $result; // return $equation; } $a = 2; $b = 3; $c = 5; $f1 = "a*b+c"; $f1 = str_replace("a", $a, $f1); $f1 = str_replace("b", $b, $f1); $f1 = str_replace("c", $c, $f1); evalmath($f1); /*if ( $equation != "" ){ $result = @eval("return " . $equation . ";" ); } if ($result == null) { throw new Exception("Unable to calculate equation"); } echo $result;*/ ?>

回答by S.Thiongane

evalEvaluates the given code as PHP. Meaning that it will execute the given paremeter as a PHP piece of code.

eval将给定的代码评估为PHP。这意味着它将作为 PHP 代码段执行给定的参数。

To correct your code, use this :

要更正您的代码,请使用以下命令:

$formulaInterpreter = new FormulaInterpreter("x + y", ["x" => 10, "y" => 20]);

回答by Carlos Espinoza

This method has two major drawbacks:

这种方法有两个主要缺点:

  • Security, php script is being evaluated by the eval function. This is bad, especially when the user wants to inject malicious code.

  • Complexity

  • 安全,php 脚本正在由 eval 函数进行评估。这很糟糕,尤其是当用户想要注入恶意代码时。

  • 复杂

I created this, check it out: Formula Interpreter

我创建了这个,检查一下:公式解释器

How does it work ?

它是如何工作的 ?

First, create an instance of FormulaInterpreterwith the formula and its parameters

首先,FormulaInterpreter用公式及其参数创建一个实例

echo $formulaInterpreter->execute();

Use the execute()method to interpret the formula. It will return the result:

使用execute()方法来解释公式。它将返回结果:

echo (new FormulaInterpreter("x + y", ["x" => 10, "y" => 20]))->execute();

in a single line

在一行中

# Formula: speed = distance / time
$speed = (new FormulaInterpreter("distance/time", ["distance" => 338, "time" => 5]))->execute() ;
echo $speed;


#Venezuela night overtime (ordinary_work_day in hours): (normal_salary * days_in_a_work_month)/ordinary_work_day
$parameters = ["normal_salary" => 21000, "days_in_a_work_month" => 30, "ordinary_work_day" => 8];
$venezuelaLOTTTArt118NightOvertime = (new FormulaInterpreter("(normal_salary/days_in_a_work_month)/ordinary_work_day", $parameters))->execute();
echo $venezuelaLOTTTArt118NightOvertime;


#cicle area
$cicleArea = (new FormulaInterpreter("3.1416*(radio*radio)", ["radio" => 10]))->execute();
echo $cicleArea;

Examples

例子

 protected function getStringArthmeticOperation($value, $deduct)
{
    if($value > 0){
        $operator = '-';
    }else{
        $operator = '+';
    }
    $mathStr = '$value $operator $deduct';
    eval("$mathStr = \"$mathStr\";");
    $userAvailableUl = eval('return '.$mathStr.';');
    return $userAvailableUl;
}

$this->getStringArthmeticOperation(3, 1); //2

About the formulas

关于公式

  1. It must contain at least two operands and an operator.
  2. Operands' name could be in upper or lower case.
  3. By now, math functions as sin, cos, pow… are not included. I'm working to include them.
  4. If your formula is not valid, you will get an error message like: Error, your formula (single_variable) is not valid.
  5. Parameters' values must be numeric.
  1. 它必须至少包含两个操作数和一个运算符。
  2. 操作数的名称可以是大写或小写。
  3. 现在,sin、cos、pow 等数学函数不包括在内。我正在努力将它们包括在内。
  4. 如果您的公式无效,您将收到如下错误消息:错误,您的公式 (single_variable) 无效。
  5. 参数的值必须是数字。

You can improve it if you want to!

如果你愿意,你可以改进它!

回答by Kaushik shrimali

Using eval function

使用 eval 函数

$ma ="2+10;";
$p = eval($ma);
print $p;

回答by ibtarek

An eval'd expression should end with ";"

eval'd 表达式应以“;”结尾

Try this :

尝试这个 :

##代码##

By the way, this is out of scope but the 'eval' function won't return the value of the expression. eval('2+10') won't return 12. If you want it to return 12, you should eval('return 2+10;');

顺便说一下,这超出了范围,但 'eval' 函数不会返回表达式的值。eval('2+10') 不会返回 12。如果你想让它返回 12,你应该 eval('return 2+10;');