php - calculate math expression from a string using eval

408

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.

672

Answer

Solution:

While I don't suggest usingeval for this (it is not the solution), the problem is thateval 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;
}
154

Answer

Solution:

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;
    }
}
50

Answer

Solution:

I recently created a PHP package that provides amath_eval helper function. It does exactly what you need, without the need to use the potentially unsafeeval 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

748

Answer

Solution:

Using eval function is very dangerous when you can't control the string argument.

Try Matex for safe Mathematical formulas calculation.

946

Answer

Solution:

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;*/
?>
111

Answer

Solution:

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

I created this, check it out: Formula Interpreter

How does it work ?

First, create an instance ofFormulaInterpreter with the formula and its parameters

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

Use theexecute() method to interpret the formula. It will return the result:

echo $formulaInterpreter->execute();

in a single line

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

Examples

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

About the formulas

  1. It must contain at least two operands and an operator.
  2. Operands' name could be in upper or lower case.
  3. By now, math functions as sin, cos, pow… are not included. I'm working to include them.
  4. If your formula is not valid, you will get an error message like: Error, your formula (single_variable) is not valid.
  5. Parameters' values must be numeric.

You can improve it if you want to!

379

Answer

Solution:

eval Evaluates the given code asPHP. 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);
638

Answer

Solution:

Using eval function

 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
108

Answer

Solution:

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

People are also looking for solutions to the problem: php - Saving multiple image input using InterventionImage

Source

Didn't find the answer?

Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.

Ask a Question

Write quick answer

Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.

Similar questions

Find the answer in similar questions on our website.