php - calcular la expresión matemática de una cadena usando eval
math (7)
Mira esto..
Lo uso en un sistema de contabilidad donde puedes escribir expresiones matemáticas en los campos de entrada de cantidades.
Ejemplos
$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
Código
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;
}
}
Quiero calcular la expresión matemática de una cadena. He leído que la solución a esto es usar eval (). Pero cuando intento ejecutar el siguiente código:
<?php
$ma ="2+10";
$p = eval($ma);
print $p;
?>
Me da el siguiente error:
Error de análisis: error de sintaxis, final inesperado en C: / xampp / htdocs / eclipseWorkspaceWebDev / MandatoryHandinSite / tester.php (4): eval () ''d código en la línea 1
¿Alguien sabe la solución a este problema?
Recientemente he creado un paquete PHP que proporciona una función de ayuda math_eval
. Hace exactamente lo que necesita, sin la necesidad de utilizar la función eval
potencialmente insegura.
Simplemente pasa la versión de la cadena de la expresión matemática y devuelve el resultado.
$two = math_eval(''1 + 1'');
$three = math_eval(''5 - 2'');
$ten = math_eval(''2 * 5'');
$four = math_eval(''8 / 2'');
También puede pasar variables, que serán sustituidas si es necesario.
$ten = math_eval(''a + b'', [''a'' => 7, ''b'' => 3]);
$fifteen = math_eval(''x * y'', [''x'' => 3, ''y'' => 5]);
Resuelto
<?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;*/
?>
Si bien no sugiero usar eval
para esto (no es la solución), el problema es que eval
espera líneas completas de código, no solo fragmentos.
$ma ="2+10";
$p = eval(''return ''.$ma.'';'');
print $p;
Debes hacer lo que quieras.
Una mejor solución sería escribir un tokenizer / parser para tu expresión matemática. Aquí hay una muy simple basada en expresiones regulares para darle un ejemplo:
$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;
}
Una expresión de evaluación debe terminar con ";"
Prueba esto :
$ma ="2+10;";
$p = eval($ma);
print $p;
Por cierto, esto está fuera del alcance, pero la función ''eval'' no devolverá el valor de la expresión. eval (''2 + 10'') no devolverá 12. Si desea que devuelva 12, debe evaluar (''return 2 + 10;'');
eval
evalúa el código dado como PHP
. Lo que significa que ejecutará el parámetro dado como un fragmento de código PHP.
Para corregir su código, use esto:
$ma ="print (2+10);";
eval($ma);