10
votes

Évaluation de l'expression mathématique

Quelle est la meilleure façon de mettre en œuvre un programme Python qui prendra une chaîne et émettra son résultat en fonction de la priorité de l'opérateur (par exemple: "4 + 3 * 5" sortira 19). J'ai googlé pour des moyens de résoudre ce problème, mais ils étaient tous trop complexes et je cherche un (relativement) simple.

Clarification: j'ai besoin de quelque chose de légèrement plus avancé que Eval () - Je souhaite pouvoir ajouter d'autres opérateurs (par exemple un opérateur maximum - 4 $ 2 = 4) ou, aussi je suis plus intéressé par cela académique que professionnelle - Je veux savoir comment faire cela.


5 commentaires

Docs.python.org/reference/simple_stmts.html#exec


Regardez: Stackoverflow.com/Questtions/400050/...


Essayez "Évaluer" au lieu de "Résoudre" qui suggère de pouvoir trouver "x" donné "4x - 6 = 4".


"Je veux configurer d'autres opérateurs". Soupir. Vous n'auriez-vous pas dit cela depuis le début?


Ressources du compilateur: Stackoverflow.com/Questtions/1669/Learning- Pour écrire-A-Compile R et quelques nouvelles implémentations: Stackoverflow.com/Questions/1384811/... et Stackoverflow.com/questions/1538964/... et Stackoverflow.com/questions/928563/...


6 Réponses :


1
votes

Je ne suis pas terriblement familier avec Python et toutes les méthodes extrêmement pythoniques, mais vous pouviez regarder le Interprète Motif , qui est défini dans le gang de quatre livres. Il est conçu pour traiter une "langue" et des expressions mathématiques suivent une langue particulière avec des règles. En fait, l'exemple sur Wikipedia est en fait une mise en œuvre Java d'une calculatrice de RPN.


8 commentaires

Donc, leur appel à l'analyse d'un "modèle" maintenant aussi? Cela doit être le mot le plus surutilisé en informatique ...


Ce n'est pas juste analyser. Il analyse des "phrases" dans une "langue" donnée de manière propre et compréhensible.


@Thomas: Ce n'est pas plus spécifique que l'analyse générique, vraiment. Je veux dire, toutes analyses impliquent des "phrases" de quelque sorte; et tout anal d'analyseur décent propre / compréhensible, du moins sous une forme. (Voir la descente récursive à titre d'exemple.) Aussi, S / Leur / Ils: P


L'interprète était un modèle de GOF d'origine. L'exemple est la conception (très) de niveau élevé d'une simple bibliothèque de regex. Il suggère d'utiliser une AST pour la description de la langue, essentiellement plutôt que (peut-être aussi bien que) pour l'entrée analysée. Devrait fonctionner pour une descente récursive, mais cela ne couvre pas comment le faire. Vraiment, je ne pense pas que cela devrait être dans le livre - vous n'avez besoin que d'une bibliothèque de regex et (peut-être) une bibliothèque d'évaluateurs d'expression, pas un motif. Au-delà de cela son temps pour Lex, Yacc et Amis.


@Noldorin: "Donc, leur appel à l'analyse d'un" modèle "maintenant aussi?" J'aime comment vous dites que, comme si le livre Gof a été libéré au cours des deux derniers mois. Le modèle d'interprète est un peu plus qu'une analyse. Il définit une méthode éprouvée de lecture dans les données et de la structurer de manière utilisable. J'ai vu d'autres tentatives de l'analyse qui ont abouti à un gâchis brouillé.


@Thomas - RPN n'est pas très impressionnant. La seule analyse réelle est la grammaire régulière pour les jetons - et l'exemple GOF d'origine était un gestionnaire de regex. Pour une représentation suffisamment simple de jeton, vous n'avez pas besoin d'une grammaire du tout pour RPN - vous n'avez besoin que d'une pile. C'est tout le point de RPN.


@ Steve314 Je n'ai pas souvenu de l'exemple dans le livre Gof. Je ne l'ai pas à côté de moi au travail. Cependant, vous êtes correct - RPN ne démontre pas la véritable puissance du modèle d'interprète.


HMMM - Je vais peut-être avoir besoin de rétracter que "ne devrait pas être une revendication de modèle". Je continue à penser à d'autres exemples. Analyseurs XML, manutentionnaires de fichiers binaires de blocs imbriqués, manutentionnaires déclaratifs-streams - E.G. Entité de jeu AIS et contrôles d'interface graphique configurables complexes, ...



2
votes

C'est ce que la fonction "eval" est en python.

vars = {'__builtins__': None, 'x': x}
result = eval(expression, vars, {})


10 commentaires

Le problème avec EVAL vient quand Expression = "System.os (RM -RF)". Si vous l'exécutez en tant que root In * Nix, la flèche va la machine. Ou si c'est l'équivalent de Windows, surtout car il y a beaucoup trop de personnes exécutant des fenêtres comme administrateur.


Seulement si vous avez effectué à partir du système d'importation d'OS et ne fournit pas le répertoire global et local. Que je fais dans mes exemples pour cette raison.


À l'intérieur de l'expression, vous pouvez encore importer un système à partir du système d'exploitation, puis l'utiliser. Donc, oui, mon exemple ne fonctionnerait que si vous importez déjà un système d'exploitation à partir du système, mais en développant mon expression, vous pouvez importer tout ce que vous voulez et l'utiliser.


@THOMAS: Si vous exécutez comme root dans un environnement ou administrateur Linux dans Windows Terre, vous méritez la justice que cela se traduit.


D.Shawley: C'est vrai, mais vous ne pouvez jamais savoir ce que font vos utilisateurs finaux. Par exemple, maintenant au travail, je suis en train d'exécuter en tant qu'administrateur sous Windows. Pas de restrictions.


Heh, je ne savais pas sur le __ importer __ astuce. Cependant, vous pouvez vous déplacer aussi. J'ai mis à jour la réponse.


@ D.Shawley: Qu'en est-il de l'utilisateur pauvre qui ne fonctionne pas en tant que root et ne perd que tous ses propres fichiers - il mérite-t-il de quoi cela se traduit?


Et que diriez-vous d'Eval ("[2 ** (10 ** A) pour une plage (100000)]", vars, {})?


@Matthewwilkes puis vous manquerez de mémoire. :)


Pas assez longtemps. Le point est que si vous autorisez des expressions génératrices ou des compréhensions, vous vous ouvrez pour les attaques de service de refus.



16
votes

Si vous êtes "intéressé acadétiquement", vous voulez apprendre comment écrire un analyseur avec la priorité de l'opérateur.

Un analysement simple de haut en bas dans Python est un bel article qui Construit un exemple d'analyseur pour faire exactement ce que vous voulez faire: évaluer les expressions mathématiques.

Je peux fortement recommander de vous rendre à la rédaction de votre premier parseur - c'est l'une de ces "Ah, c'est comment cela fonctionne" Moments!


1 commentaires

J'ai parcouru un aspect très rapide et il semble que l'article que vous avez lié à implémente le modèle d'interprète en Python.



2
votes

Une autre possibilité est de regarder PyparSing , qui est un constructeur général d'analyseur. Il est plus puissant que nécessaire, mais cela peut être plus rapide à mettre en œuvre.


2 commentaires

Le wiki pygarsing (pygarsing.wikispaces.com) comprend quelques exemples d'un analyseur d'expression arithmétique - Fourfn.py et SimpleArth.py. Même si vous n'utilisez pas de pyparsing, Fourfn.py est susceptible d'éclairer comment un tel analyseur implémente la priorité de l'opérateur.


Je viens de me rendre compte que l'OP voulait ajouter d'autres opérateurs. SimpleArth.py montre comment ajouter un opérateur factorielle (!) - Evalarith.py (au bas de la page) élargit SimpleArth.py et montre comment évaluer les valeurs analysées.




0
votes

Cette réception donne la bonne réponse à votre problème:

http://code.activestate.com/recipes/496746-Restre -Safe-eval /

Cela vous permet d'évaluer une instruction limitée qui ne peut pas nuire à votre ordinateur ou à votre programme.


0 commentaires