calculate math expression from a string using eval

2019-01-01 02:22发布

问题:

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;\');



标签: php math eval