2009-10-09 25 views
10

¿Cuál es la mejor manera de implementar un programa python que tomará una cadena y dará salida a su resultado según la precedencia del operador (por ejemplo: "4 + 3 * 5" dará salida 19). Busqué en Google formas de resolver este problema, pero todas eran demasiado complejas y busco una (relativamente) simple.Evaluación de expresión matemática

aclaración: Necesito algo más avanzado que eval() - Quiero poder agregar otros operadores (por ejemplo, un operador máximo - 4 $ 2 = 4) o, también estoy más interesado académicamente que profesionalmente - Quiero saber cómo para hacer esto.

+1

http://docs.python.org/reference/simple_stmts.html#exec – nlucaroni

+1

Eche un vistazo a: http: // stackoverflow.com/questions/400050/reading-and-running-a-mathematical-expression-in-python –

+1

Pruebe "evaluar" en lugar de "resolver", lo que sugiere poder encontrar "x" dado "4x - 6 = 4". – dmckee

Respuesta

16

Si está "interesado académicamente", quiere aprender cómo escribir un analizador con precedencia de operador.

Simple Top-Down Parsing in Python es un buen artículo que construye un analizador de ejemplos para hacer exactamente lo que quiere hacer: Evaluar expresiones matemáticas.

Recomiendo probar mi propio primer analizador, es uno de esos "ah, que es cómo funciona" ¡momentos!

+0

Eché un vistazo muy rápido y parece que el artículo al que se vinculó implementa el patrón de Intérprete en Python. –

1

No estoy terriblemente familiarizado con Python y cualquier método extremadamente Pythonic, pero podría mirar el Interpreter pattern, que se define en el libro Gang of Four. Está diseñado para procesar un "idioma", y las expresiones matemáticas siguen un lenguaje particular con reglas. De hecho, el ejemplo en Wikipedia es en realidad una implementación de Java de una calculadora RPN.

+18

¿Entonces su llamada analiza un "patrón" ahora también? Esta debe ser la palabra más usada en informática ... – Noldorin

+0

No es solo un análisis sintáctico. Es analizar "oraciones" en un "lenguaje" dado de una manera clara y comprensible. –

+1

@Thomas: Eso no es más específico que el análisis genérico, realmente. Quiero decir, todo análisis implica "oraciones" de algún tipo; y cualquier analizador decente es limpio/comprensible, al menos en alguna forma. (Ver descenso recursivo como ejemplo.) Además, s/their/they son: P – Noldorin

1

Eso es lo que hace la función "eval" en Python.

result = eval(expression) 

Sin embargo, Aviso que puede hacer mucho más, sobre todo llamar funciones, por lo que es seguro que usted debe asegurarse de que no se puede acceder a los locales o globales. También, puede acceder a los métodos incorporados, incluyendo el complicado importación por lo que necesita para bloquear el acceso a dicho así:

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

Pero eso es sólo si es necesario de seguridad, es decir si se permite a nadie que escriba cualquier expresión

Por supuesto, ya que de esta manera bloquea el uso de todas las variables de locla, entonces no tiene ninguna variable para usar, por lo que para eso tiene que pasar solo las variables a las que se debe acceder en los diccionarios.

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

o similar.

+1

El problema con eval se produce cuando expression = "system.os (rm -rf \)". Si lo ejecuta como root en * nix, la pluma se mueve hacia la máquina. O si es el equivalente de Windows, especialmente porque hay demasiadas personas que ejecutan Windows como administrador. –

+2

Solo si ha realizado 'from os import system' y no proporciona el directorio global y local. Lo cual hago en mis ejemplos por este motivo. –

+0

Expresión interna, puede importar el sistema desde el sistema operativo y luego usarlo. Entonces sí, mi ejemplo solo funcionaría si ya importas el sistema operativo desde el sistema, pero al expandir mi expresión, puedes importar lo que quieras y usarlo. –

2

Otra posibilidad es mirar Pyparsing, que es un creador de analizador general. Es más poderoso de lo que necesita, pero puede ser más rápido de implementar.

+0

El wiki de pyparsing (pyparsing.wikispaces.com) incluye un par de ejemplos de un analizador de expresiones aritméticas: fourFn.py y simpleArith.py. Incluso si no usa pyparsing, es probable que fourFn.py sea esclarecedor en la forma en que dicho analizador implementa la precedencia del operador. – PaulMcG

+0

Me acabo de dar cuenta de que OP desea agregar otros operadores. simpleArith.py muestra cómo agregar un operador factorial (!) - evalArith.py (en la parte inferior de la página) expande simpleArith.py y muestra cómo evaluar los valores analizados. – PaulMcG

Cuestiones relacionadas