我想从字符串计算数学表达式。我已经了解到解决方法是使用eval()。但是当我尝试运行以下代码时:
<?php
$ma ="2+10";
$p = eval($ma);
print $p;
?>
我遇到了以下错误:
解析错误:语法错误,意外的 $end,位于 C:\xampp\htdocs\eclipseWorkspaceWebDev\MandatoryHandinSite\tester.php(4) : eval()‘d code on line 1
有人知道解决这个问题的方法吗?
虽然我不建议使用 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;
}
$matches[1]
和 $matches[3]
或类似位置周围使用 str_replace
来去掉这些空格,那么计算就无法完全正确。这将完全依赖于您的用法 - 这适合我的需求。 /([\d\.\s]+)([\+\-\*\/])([\d\.\s]+)/
- Warren Sergent/([\d\.\s]+)([\+\-\*\/])(\-?[\d\.\s]+)/
将允许第二个数字是负值(例如 24.5 * -4 的情况)。否则,由于第二个分组无法找到负数,这将会出错。 - Warren Sergent看一下这个..
我在一个会计系统中使用它,您可以在金额输入字段中编写数学表达式..
$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;
}
}
0.3
和许多其他数字没有有限的二进制表示,因此计算机必须进行一些舍入。同样地,2/3
没有有限的十进制表示,因此我们可能会将其舍入为0.6666666667
。 - mbomb007最近我创建了一个PHP包,提供了一个名为math_eval
的辅助函数。它能够精确地完成你需要的功能,而无需使用可能不安全的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]);
解决了!
<?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;*/
?>
if (preg_match('/^[0-9\+\-\*\/\(\)\.]+$/', $mathString)) {
$value = eval('return
' . $mathString . ';');
} else {
throw new \Exception('Invalid calc() value: ' . $mathString);
}
它仍然易于使用,但相对安全。它可以处理任何基本的数学计算,例如(10*(1+0.2))
,这在这里提到的大多数解决方案中都不可能实现。
安全性,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;
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
eval
函数将给定的代码作为PHP
代码进行评估。这意味着它将执行给定的参数作为PHP代码片段。
要更正您的代码,请使用以下内容:
$ma ="print (2+10);";
eval($ma);
eval() 函数中的表达式应该以 ";" 结尾。
尝试以下代码:
$ma ="2+10;";
$p = eval($ma);
print $p;
$p
变量为空。在内部添加echo
:$ma ="echo 2+10;";
- S.Thiongane
eval()
来完成某些事情,但绝不能在任何情况下使用eval()
。看看这个解决方案。 - Sammitch$ma
字符串来自哪里?用户输入?如果我发送rmdir('/var/www');
或其他内容作为我的输入,会怎样? - gen_Eric