math - origen - opiniones sobre la corriente del diseño inteligente
¿Diseño inteligente de un analizador matemático? (9)
¿Cuál es la forma más inteligente de diseñar un analizador matemático? Lo que quiero decir es una función que toma una cadena matemática (como: "2 + 3/2 + (2 * 5)") y devuelve el valor calculado? Escribí uno en VB6 hace años, pero terminó siendo inflado y no muy portátil (o inteligente para el caso ...). Ideas generales, código psuedo o código real es apreciado.
ANTLR es un muy agradable generador de analizadores LL (*). Lo recomiendo mucho
Escribí algunas publicaciones en el blog sobre el diseño de un analizador matemático. Hay una introduction general, conocimiento básico sobre grammars , implementación de muestra escrita en Ruby y un conjunto de pruebas . Tal vez encuentres estos materiales útiles.
La pregunta relacionada Ecuación (expresión) analizador con precedencia? tiene buena información sobre cómo comenzar con esto también.
-Adán
Los desarrolladores siempre quieren tener un enfoque limpio e intentar implementar la lógica de análisis desde cero, por lo general terminando con el algoritmo Dijkstra Shunting-Yard . El resultado es un código que se asemeja, pero posiblemente esté plagado de errores. He desarrollado tal API, JMEP , que hace todo eso, pero me llevó años tener un código estable.
Incluso con todo ese trabajo, puede ver incluso desde esa página de proyecto que estoy considerando seriamente cambiar a usar JavaCC o ANTLR, incluso después de todo ese trabajo ya hecho.
Sé que esto es viejo, pero me encontré con esto tratando de desarrollar una calculadora como parte de una aplicación más grande y encontré algunos problemas utilizando la respuesta aceptada. Los enlaces fueron INMENSALMENTE útiles para comprender y resolver este problema y no deben descontarse. Estaba escribiendo una aplicación de Android en Java y para cada elemento en la expresión "cadena", en realidad almacené una cadena en una lista de arreglos a medida que el usuario escribe en el teclado. Para la conversión de infijo a posfijo, iteraba a través de cada String en ArrayList, y luego evaluaba el arreglo ArrayList de cadenas recién creado. Esto fue fantástico para una pequeña cantidad de operandos / operadores, pero los cálculos más largos fueron consistentemente desactivados, especialmente cuando las expresiones comenzaron a evaluar a los no enteros. En el enlace proporcionado para la conversión Infix a Postfix , sugiere abrir la pila si el elemento escaneado es un operador y el elemento topStack tiene una precedencia más alta. Descubrí que esto es casi correcto. Apareciendo el elemento topStack si su precedencia es mayor O IGUAL al operador escaneado finalmente hizo que mis cálculos salgan correctos. Esperemos que esto ayude a cualquiera que trabaje en este problema, y gracias a Justin Poliey (y fas?) Por proporcionar algunos enlaces invaluables.
Si tiene una aplicación "siempre activada", solo publique la cadena matemática en google y analice el resultado. De manera sencilla, pero no estoy seguro si eso es lo que necesitas, pero de alguna manera inteligente, supongo.
Suponiendo que su entrada es una expresión infija en formato de cadena, puede convertirla a postfix y, usando un par de pilas: una pila de operador y una pila de operandos, trabaje la solución desde allí. Puede encontrar información general sobre algoritmos en el enlace de Wikipedia.
Tienes un par de enfoques. Puede generar código dinámico y ejecutarlo para obtener la respuesta sin necesidad de escribir mucho código. Simplemente realice una búsqueda en el código generado en tiempo de ejecución en .NET y hay muchos ejemplos a su alrededor.
Alternativamente, puede crear un analizador real y generar un pequeño árbol de análisis que luego se utiliza para evaluar la expresión. De nuevo, esto es bastante simple para expresiones básicas. Echa un vistazo a codeplex ya que creo que tienen un analizador matemático allí. O simplemente busque BNF, que incluirá ejemplos. Cualquier sitio web que presente conceptos de compilación incluirá esto como un ejemplo básico.
Un enfoque bastante bueno implicaría dos pasos. El primer paso consiste en convertir la expresión de infijo a postfijo (por ejemplo, mediante el yardaje de maniobras de Dijkstra ). Una vez hecho esto, es bastante trivial escribir un evaluador de postfijo .