25

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

<?php

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

?>

它给了我以下错误:

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

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

4

9 回答 9

69

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

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

应该做你想做的。


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

$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;
}
于 2013-09-18T19:36:21.193 回答
39

看看这个..

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

例子

$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

代码

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;
    }
}
于 2014-11-22T12:29:02.100 回答
6

math_eval我最近创建了一个提供帮助函数的 PHP 包。它完全符合您的需要,而无需使用可能不安全的eval功能。

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

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

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

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

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

于 2018-11-01T14:43:26.483 回答
4

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

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

于 2017-09-20T16:37:22.483 回答
1

解决了!

<?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", "\$$0", $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;*/
?>
于 2017-04-16T07:37:43.743 回答
1

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

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

  • 复杂

我创建了这个,看看:公式解释器

它是如何工作的 ?

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

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

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

echo $formulaInterpreter->execute();

在一行中

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

例子

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

关于公式

  1. 它必须至少包含两个操作数和一个运算符。
  2. 操作数的名称可以是大写或小写。
  3. 到目前为止,不包括 sin、cos、pow 等数学函数。我正在努力将它们包括在内。
  4. 如果您的公式无效,您将收到如下错误消息:错误,您的公式 (single_variable) 无效。
  5. 参数的值必须是数字。

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

于 2019-03-20T10:17:39.027 回答
0

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

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

$ma ="print (2+10);";
eval($ma);
于 2013-09-18T19:40:09.203 回答
0

使用评估功能

 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
于 2019-04-26T12:20:30.477 回答
-2

一个 eval 的表达式应该以 ";" 结尾

尝试这个 :

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

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

于 2013-09-18T19:42:04.170 回答