web-dev-qa-db-fra.com

calculer une expression mathématique à partir d'une chaîne en utilisant eval

Je veux calculer une expression mathématique à partir d'une chaîne. J'ai lu que la solution à cela est d'utiliser eval (). Mais quand j'essaye de lancer le code suivant:

<?php

$ma ="2+10";
$p = eval($ma);
print $p;

?>

Cela me donne l'erreur suivante:

Erreur d'analyse: erreur de syntaxe, $ inattendu dans fin C:\xampp\htdocs\eclipseWorkspaceWebDev\MandatoryHandinSite\tester.php (4) : code eval () sur la ligne 1

Est-ce que quelqu'un connaît la solution à ce problème?.

18
Langkiller

Bien que je ne suggère pas d'utiliser eval pour cela (c'est pas la solution), le problème est que eval attend des lignes de code complètes, pas seulement des fragments.

$ma ="2+10";
$p = eval('return '.$ma.';');
print $p;

Devrait faire ce que vous voulez.


Une meilleure solution serait d’écrire un tokenizer/analyseur syntaxique pour votre expression mathématique. Voici un exemple très simple basé sur regex pour vous donner un exemple:

$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;
}
40
Rocket Hazmat

Regarde ça..

J'utilise cela dans un système de comptabilité où vous pouvez écrire des expressions mathématiques dans des champs de saisie de montant.

Exemples

$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;
    }
}
28
clarkk

L'utilisation de eval function est très dangereuse lorsque vous ne pouvez pas contrôler l'argument de chaîne.

Essayez Matex pour un calcul sûr des formules mathématiques.

1
Marcodor

J'ai récemment créé un paquet PHP qui fournit une fonction d'assistance math_eval. Il fait exactement ce dont vous avez besoin, sans avoir à utiliser la fonction eval potentiellement non sécurisée. 

Vous venez de transmettre la version chaîne de l'expression mathématique et le résultat est renvoyé.

$two   = math_eval('1 + 1');
$three = math_eval('5 - 2');
$ten   = math_eval('2 * 5');
$four  = math_eval('8 / 2');

Vous pouvez également transmettre des variables, qui seront substituées si nécessaire.

$ten     = math_eval('a + b', ['a' => 7, 'b' => 3]);
$fifteen = math_eval('x * y', ['x' => 3, 'y' => 5]);

Lien: https://github.com/langleyfoxall/math_eval

1
DivineOmega

eval EVALUE LE CODE DONN&EACUTE; EN TANT QUE PHP. Cela signifie qu'il exécutera le paramètre spécifié en tant que morceau de code PHP. 

Pour corriger votre code, utilisez ceci:

$ma ="print (2+10);";
eval($ma);
0
S.Thiongane

Résolu!

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