可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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:
<?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
Does someone know the solution to this problem.
回答1:
While I don\'t suggest using eval
for this (it is not the solution), the problem is that eval
expects complete lines of code, not just fragments.
$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;
}
回答2:
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;
}
}
回答3:
Using eval function is very dangerous when you can\'t control the string argument.
Try Matex for safe Mathematical formulas calculation.
回答4:
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.
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
回答5:
eval
Evaluates the given code as PHP
. Meaning that it will execute the given paremeter as a PHP piece of code.
To correct your code, use this :
$ma =\"print (2+10);\";
eval($ma);
回答6:
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\", \"\\$$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;*/
?>
回答7:
An eval\'d expression should end with \";\"
Try this :
$ma =\"2+10;\";
$p = eval($ma);
print $p;
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;\');