Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

calculate math expression from a string using eval

Tags:

php

math

eval

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.

like image 640
Langkiller Avatar asked Sep 18 '13 19:09

Langkiller


People also ask

What does eval () do in Python?

Python's eval() allows you to evaluate arbitrary Python expressions from a string-based or compiled-code-based input. This function can be handy when you're trying to dynamically evaluate Python expressions from any input that comes as a string or a compiled code object.

How do you evaluate a string expression in PHP?

The eval() function evaluates a string as PHP code. The string must be valid PHP code and must end with semicolon. Note: A return statement will terminate the evaluation of the string immediately. Tip: This function can be useful for storing PHP code in a database.

How do you evaluate a string expression in JavaScript?

The eval() function in JavaScript is used to evaluate the expression. It is JavaScirpt's global function, which evaluates the specified string as JavaScript code and executes it. The parameter of the eval() function is a string. If the parameter represents the statements, eval() evaluates the statements.


2 Answers

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; } 
like image 197
Rocket Hazmat Avatar answered Sep 19 '22 12:09

Rocket Hazmat


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;     } } 
like image 41
clarkk Avatar answered Sep 18 '22 12:09

clarkk