Débutant
🧠 Fondamentaux
10 XP
0 personnes ont réussi
Outil : calculatrice securisee
Les LLM sont nuls en maths. Demande a ChatGPT de calculer 17.3 * 28.7 et il y a de bonnes chances qu'il se trompe. C'est logique : un modele de langage predit le prochain token, il ne fait pas d'arithmetique. La solution, c'est de lui donner un outil calculatrice.
Mais attention : pas question d'utiliser eval() pour executer du code arbitraire. Si un utilisateur envoie eval("__import__('os').system('rm -rf /')"), c'est la catastrophe. Il faut une calculatrice qui ne peut faire que des maths.
La solution propre passe par le module ast (Abstract Syntax Tree) de Python. Tu peux parser une expression mathematique en arbre syntaxique et n'evaluer que les operations autorisees : addition, soustraction, multiplication, division, puissance, et les nombres.
def evaluer_noeud(noeud): if isinstance(noeud, ast.Constant): return noeud.value # un nombre if isinstance(noeud, ast.BinOp): gauche = evaluer_noeud(noeud.left) droite = evaluer_noeud(noeud.right) return OPERATIONS[type(noeud.op)](gauche, droite) if isinstance(noeud, ast.UnaryOp) and isinstance(noeud.op, ast.USub): return -evaluer_noeud(noeud.operand)
Ecris une fonction calculer(expression) qui prend une expression mathematique sous forme de string et renvoie le resultat numerique. Elle ne doit accepter que des nombres et les operations +, -, *, /, **. Si l'expression est invalide ou contient autre chose (appels de fonction, variables...), elle doit renvoyer un dictionnaire {"error": "Expression invalide"}.
r = calculer("import os")
assert isinstance(r, dict) and "error" in r, "Une expression invalide doit retourner un dict avec 'error'"
r2 = calculer("print('hello')")
assert isinstance(r2, dict) and "error" in r2
r3 = calculer("abc + 1")
assert isinstance(r3, dict) and "error" in r3
+ 0 tests cachés
Indices (3 disponibles)
Solution officielle
import ast
import operator
OPERATIONS = {
ast.Add: operator.add,
ast.Sub: operator.sub,
ast.Mult: operator.mul,
ast.Div: operator.truediv,
ast.Pow: operator.pow,
}
def evaluer_noeud(noeud):
if isinstance(noeud, ast.Constant) and isinstance(noeud.value, (int, float)):
return noeud.value
if isinstance(noeud, ast.BinOp) and type(noeud.op) in OPERATIONS:
gauche = evaluer_noeud(noeud.left)
droite = evaluer_noeud(noeud.right)
return OPERATIONS[type(noeud.op)](gauche, droite)
if isinstance(noeud, ast.UnaryOp) and isinstance(noeud.op, ast.USub):
return -evaluer_noeud(noeud.operand)
raise ValueError("Noeud non autorise")
def calculer(expression):
try:
arbre = ast.parse(expression, mode="eval")
resultat = evaluer_noeud(arbre.body)
return resultat
except Exception:
return {"error": "Expression invalide"}