Skip to content

Instantly share code, notes, and snippets.

@DBX12
Last active October 10, 2019 06:45
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DBX12/2e1d622a0fa0937874ac3cf5eeecef51 to your computer and use it in GitHub Desktop.
Save DBX12/2e1d622a0fa0937874ac3cf5eeecef51 to your computer and use it in GitHub Desktop.
Test of clarkk's Field_calculate
<?php
/**
* Class provided by http://stackoverflow.com/users/555222/clarkk
* in this answer http://stackoverflow.com/a/27077376
*/
class Field_calculate {
const PATTERN = '/(?:\-?\d+(?:\.?\d+)?[\+\-\*\/])+\-?\d+(?:\.?\d+)?/';
const PARENTHESIS_DEPTH = 10;
public function calculate($input){
$input = str_replace(' ','',$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]);
}
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;
}
}
<?php
require "Field_calculate.php";
$calc = new Field_calculate();
$tests = [
[
'expr' => '3/18-1/2 * 40',
'res' => -19.8333333
],
[
'expr' => '13/18 * 40',
'res' => 28.88888888
],
[
'expr' => '14 3/16/ 21 * 40',
'res' => false
],
[
'expr' => '16 3/16/ 23 * 40',
'res' => false
],
[
'expr' => '16-3/16 / 30 * 60',
'res' => 15.625
],
[
'expr' => '9.75 * 21.5/29.5',
'res' => 710.593220339
],
[
'expr' => '1/4 * 5',
'res' => 1.25
],
[
'expr' => '1/2 * 6',
'res' => 3
],
[
'expr' => '7 * 60',
'res' => 420
],
[
'expr' => '8 Ga. x 4',
'res' => 32
],
[
'expr' => '22 x 36',
'res' => 792
],
[
'expr' => '35/64 * 6',
'res' => 3.28125
],
[
'expr' => '100 -10',
'res' => 90
],
[
'expr' => '100 - 10',
'res' => 90
]
];
foreach($tests as $test){
$res = $calc->calculate($test['expr']);
echo "Expression: {$test['expr']}".PHP_EOL;
echo "Expected: {$test['res']}".PHP_EOL;
echo 'Calculated: '.$res.PHP_EOL;
echo 'Test '.(($res == $test['res']) ? 'passed' : 'failed');
echo PHP_EOL;
echo '------------------------'.PHP_EOL;
}
@hoanganh25991
Copy link

hi @DBX12,

Field_calculate's really helpful.
But look like $input = preg_replace('[^0-9\.\+\-\*\/\(\)]', '', $input); not work well to remove space in my case;

$formula = '100 -10'; // or '100 -  10'
$result = (new Field_calculate)->calculate($formula); // return 0

@DBX12
Copy link
Author

DBX12 commented Dec 5, 2017

Hey @hoanganh25991,
thanks for the feedback. I'm not the creator of the class, I just hacked a short test script for a StackOverflow user, who wanted to know if it can solve certain expressions (in fact, exactly the expressions in the $expressions array).
After updating the tests, I realized, the class does not behave as expected. As it was only a test for a SO user of a class provided by an internet stranger, I do not plan to fix it in the near future - sorry.
However help by PR (not sure, if it's supported for gists) is welcome.
Greetings,
DBX12

Copy link

ghost commented Nov 21, 2018

Field_calculate's is really helpful.
i have a problem in use it.
return "Function create_function() is deprecated" for me!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment