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
calculate math expression from a string using eval
提问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 eval
for this (it is notthe solution), the problem is that eval
expects 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
回答by DivineOmega
I recently created a PHP package that provides a math_eval
helper function. It does exactly what you need, without the need to use the potentially unsafe eval
function.
我最近创建了一个提供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]);
回答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
eval
Evaluates 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 FormulaInterpreter
with 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
关于公式
- It must contain at least two operands and an operator.
- Operands' name could be in upper or lower case.
- By now, math functions as sin, cos, pow… are not included. I'm working to include them.
- If your formula is not valid, you will get an error message like: Error, your formula (single_variable) is not valid.
- Parameters' values must be numeric.
- 它必须至少包含两个操作数和一个运算符。
- 操作数的名称可以是大写或小写。
- 现在,sin、cos、pow 等数学函数不包括在内。我正在努力将它们包括在内。
- 如果您的公式无效,您将收到如下错误消息:错误,您的公式 (single_variable) 无效。
- 参数的值必须是数字。
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;');