Parse math operations with PHP
This should be pretty secure:
function do_maths($expression) {
eval('$o = ' . preg_replace('/[^0-9\+\-\*\/\(\)\.]/', '', $expression) . ';');
return $o;
}
echo do_maths('1+1');
calculate math expression from a string using eval
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;
}
PHP - Parse mathematical equations inside strings
preg_match_all('/\[(.*?)\]/', $string, $out);
foreach ($out[1] as $k => $v)
{
eval("\$result = $v;");
$string = str_replace($out[0][$k], $result, $string);
}
This code is highly dangerous if the strings are user inputs because it allows any arbitrary code to be executed
How to convert a string to numbers that include math operations in it?
If your equations stay pretty simple you can make a function similar to the following:
function calcString($str)
{
$patten = '/[\*\/\+-]/';
preg_match($patten,$str, $operator);
$arr = preg_split($patten,$str);
switch($operator[0]){
case '-':
return $arr[0] - $arr[1];
case '+':
return $arr[0] + $arr[1];
case '*':
return $arr[0] * $arr[1];
case '/':
return $arr[0] / $arr[1];
}
}
$num = "10+2";
echo calcString($num); // Output = 12
// Or
$num = "10-2";
echo calcString($num); // Output = 8
// Or
$num = "10*2";
echo calcString($num); // Output = 20
// Or
$num = "10/2";
echo calcString($num); // Output = 5
Of course you could put the function is some kind of helper class.
How to split some numbers and math operator in PHP?
You can try like this - based upon answer elsewhere on stack. Modified the pattern and added the preg_replace so that the results are not affected by spaces in the input string.
$input = '2 + 3 * 7';
$input = '2-5/3.4';
$pttn='@([-/+\*])@';
$out=preg_split( $pttn, preg_replace( '@\s@', '', $input ), -1, PREG_SPLIT_DELIM_CAPTURE );
printf('<pre>%s</pre>',print_r( $out, true ) );
Will output:
Array
(
[0] => 2
[1] => -
[2] => 5
[3] => /
[4] => 3.4
)
Update:
$input = '2 + 5 - 4 / 2.6';
$pttn='+-/*'; # standard mathematical operators
$pttn=sprintf( '@([%s])@', preg_quote( $pttn ) ); # an escaped/quoted pattern
$out=preg_split( $pttn, preg_replace( '@\s@', '', $input ), -1, PREG_SPLIT_DELIM_CAPTURE );
printf('<pre>%s</pre>',print_r( $out, true ) );
outputs:
Array
(
[0] => 2
[1] => +
[2] => 5
[3] => -
[4] => 4
[5] => /
[6] => 2.6
)
Perform a mathematical operation after retrieving from another file
But echoing the content is displaying the original content (i.e 2+3)
rather than displaying the output(i.e 5).
This is completely expected behaviour. You read a string from a file. How should PHP know that you want it to calculate the expression?
You have to implement a simple parser (or search one on the Internet) which analyses the expression and caulates the result.
dave1010 provided a very nice function in one of his posts:
function do_maths($expression) {
eval('$o = ' . preg_replace('/[^0-9\+\-\*\/\(\)\.]/', '', $expression) . ';');
return $o;
}
echo do_maths('1+1');
But note that this can still halt your script execution if the input contains a syntax error!
Here is a better library which uses a real parser: https://github.com/stuartwakefield/php-math-parser
How to mathematically evaluate a string like 2-1 to produce 1?
I know this question is old, but I came across it last night while searching for something that wasn't quite related, and every single answer here is bad. Not just bad, very bad. The examples I give here will be from a class that I created back in 2005 and spent the past few hours updating for PHP5 because of this question. Other systems do exist, and were around before this question was posted, so it baffles me why every answer here tells you to use eval
, when the caution from PHP is:
The eval() language construct is very dangerous because it allows execution of arbitrary PHP code. Its use thus is discouraged. If you have carefully verified that there is no other option than to use this construct, pay special attention not to pass any user provided data into it without properly validating it beforehand.
Before I jump in to the example, the places to get the class I will be using is on either PHPClasses or GitHub. Both the eos.class.php
and stack.class.php
are required, but can be combined in to the same file.
The reason for using a class like this is that it includes and infix to postfix(RPN) parser, and then an RPN Solver. With these, you never have to use the eval
function and open your system up to vulnerabilities. Once you have the classes, the following code is all that is needed to solve a simple (to more complex) equation such as your 2-1
example.
require_once "eos.class.php";
$equation = "2-1";
$eq = new eqEOS();
$result = $eq->solveIF($equation);
That's it! You can use a parser like this for most equations, however complicated and nested without ever having to resort to the 'evil eval
'.
Because I really don't want this only only to have my class in it, here are some other options. I am just familiar with my own since I've been using it for 8 years. ^^
Wolfram|Alpha API
Sage
A fairly bad parser
phpdicecalc
Not quite sure what happened to others that I had found previously - came across another one on GitHub before as well, unfortunately I didn't bookmark it, but it was related to large float operations that included a parser as well.
Anyways, I wanted to make sure an answer to solving equations in PHP on here wasn't pointing all future searchers to eval
as this was at the top of a google search. ^^
Safest way to use eval to parse equations entered by a form
If you must use eval
, the eval
docs page on it has some code that will allow you to filter mathematical formulas. But as others, and the PHP docs page, have said, it's not a good idea to use eval
unless there is no other alternative.
<?php
$test = '2+3*pi';
// Remove whitespaces
$test = preg_replace('/\s+/', '', $test);
$number = '(?:\d+(?:[,.]\d+)?|pi|π)'; // What is a number
$functions = '(?:sinh?|cosh?|tanh?|abs|acosh?|asinh?|atanh?|exp|log10|deg2rad|rad2deg|sqrt|ceil|floor|round)'; // Allowed PHP functions
$operators = '[+\/*\^%-]'; // Allowed math operators
$regexp = '/^(('.$number.'|'.$functions.'\s*\((?1)+\)|\((?1)+\))(?:'.$operators.'(?2))?)+$/'; // Final regexp, heavily using recursive patterns
if (preg_match($regexp, $q))
{
$test = preg_replace('!pi|π!', 'pi()', $test); // Replace pi with pi function
eval('$result = '.$test.';');
}
else
{
$result = false;
}
?>
Related Topics
Search for Highest Key/Index in an Array
What Is the Use of <<<Eod in PHP
How to Clear Previously Echoed Items in PHP
Laravel SQLstate[Hy000] [2002] Connection Refused
File_Get_Contents Returns Empty String
How to Check If a MySQL Table Exists with PHP
How to Save Changed Simplexml Object Back to File
PHP Session with an Incomplete Object
Laravel - Decryptexception: 'The MAC Is Invalid'
Sending/Displaying a Base64 Encoded Image
Auto Increment Skipping Numbers
Php/MySQL Zip Code Proximity Search
Laravel Gmail Not Working, "Username and Password Not Accepted. Learn More..."
How to Expose All the Acf Fields to Wordpress Rest API in Both Pages and Custom Postypes
What Is a Clever Way to Count Number of Unique Items in Array (Php)
What Means Call to a Member Function on Boolean and How to Fix