Pregunta

¿Cuál es la forma más inteligente para el diseño de un analizador de matemáticas?Lo que quiero decir es una función que toma una matemática de la cadena (como por ejemplo:"2 + 3 / 2 + (2 * 5)") y devuelve el valor calculado?Me hizo escribir uno en VB6 hace años, pero terminó siendo camino a la hinchada y no muy portable (o inteligente, para el caso...).Ideas generales, pseudo código o el código real es de agradecer.

¿Fue útil?

Solución

Un buen enfoque involucra dos pasos.El primer paso consiste en la conversión de la expresión de infijo a postfijo (por ejemplo,a través de Dijkstra patio de maniobras) notación.Una vez hecho, es bastante trivial para escribir un postfix evaluador.

Otros consejos

He escrito un par de entradas de blog sobre el diseño de un analizador de matemáticas.En general, existe un introducción, conocimientos básicos acerca de la gramáticas, ejemplo de aplicación escrita en Ruby y un suite de prueba.Tal vez usted va a encontrar estos materiales útiles.

Usted tiene un par de métodos.Usted podría generar dinámicas de código y ejecutarlo con el fin de obtener la respuesta sin necesidad de escribir mucho código.Acabo de realizar una búsqueda en tiempo de ejecución de código generado en el .NET y hay un montón de ejemplos de todo.

Alternativamente, usted podría crear un analizador real y generar un poco de árbol de análisis que se utiliza para evaluar la expresión.De nuevo esto es bastante simple de expresiones básicas.Echa un vistazo codeplex como yo creo que tiene un analizador de matemáticas que hay.O simplemente buscar BNF que se incluyen ejemplos.Cualquier sitio web de la introducción del compilador de los conceptos se incluyen en este como un ejemplo básico.

Codeplex Evaluador De Expresiones

Sé que esto es viejo, pero me encontré con esta tratando de desarrollar una calculadora como parte de una mayor aplicación y corrió a través de algunos problemas con el aceptado respuesta.Los enlaces fueron de gran utilidad en la comprensión y solución de este problema y no debe ser menospreciado.Yo estaba escribiendo una aplicación de Android en Java y para cada elemento de la expresión "de cadena" en realidad yo almacena una Cadena en un objeto ArrayList como los tipos de usuario en el teclado.Para el infijo a postfijo de conversión, he reiterado a través de cada Cadena en el ArrayList, a continuación se evalúa el recién arreglado postfix ArrayList de Cadenas.Este fue fantástico para un pequeño número de operandos y operadores, pero ya los cálculos fueron consistentemente, especialmente como las expresiones que empezó a evaluar a los no enteros.En el enlace proporcionado para De infijo a Postfijo de conversión, se sugiere hacer estallar la Pila si el elemento escaneado es un operador y el topStack elemento tiene una prioridad más alta.He encontrado que esto es casi correcta.De estallar la topStack si se trata de precedencia es mayor O IGUAL que el escaneado operador finalmente mis cálculos salga correcto.Esperemos que esto ayude a alguien trabajando en este problema, y gracias a Justin Poliey (y fas?) para proporcionar algo de valor incalculable enlaces.

Si usted tiene un "always on" de la aplicación, justo después de la matemáticas de la cadena de google y analizar el resultado.De manera Simple, pero no estoy seguro si eso es lo que usted necesita - pero inteligente de alguna manera, supongo.

La pregunta relacionada con la La ecuación (expresión) analizador con prioridad? tiene buena información sobre cómo empezar con esto.

-Adam

Asumiendo que su entrada es un infijo expresión en la cadena de formato, se puede convertir a postfix y, con un par de pilas:un operador de la pila y una pila de operandos, el trabajo de la solución a partir de ahí.Usted puede encontrar algoritmo general de la información en el enlace de Wikipedia.

ANTLR es un muy buen LL(*) parser generator.Lo recomiendo altamente.

Los desarrolladores siempre quiere tener limpio el enfoque, y tratar de implementar la lógica de análisis de suelo, por lo general termina con la Dijkstra De Maniobras Patio De Algoritmo.El resultado es bonito aspecto de código, pero posiblemente plagado de bugs.He desarrollado una API, JMEP, que hace todo eso, pero me tomó años para tener estabilidad de código.

Incluso con todo ese trabajo, se puede ver que a partir de ese proyecto de la página que estoy considerando seriamente la posibilidad de cambiar a uso de JavaCC o ANTLR, incluso después de todo ese trabajo ya está hecho.

11 años en el futuro, a partir de cuando esta pregunta se le preguntó:Si usted no desea volver a inventar la rueda, hay muchas más exóticas de matemáticas de los analizadores de allí.

Hay uno que escribí años atrás, lo cual apoya las operaciones aritméticas, resolución de ecuaciones, cálculo diferencial, cálculo integral, estadística básica, la función o fórmula de definición, gráficos, etc.

Su llamado ParserNG y es gratis.

La evaluación de una expresión es tan simple como:

    MathExpression expr = new MathExpression("(34+32)-44/(8+9(3+2))-22"); 
    System.out.println("result: " + expr.solve());

    result: 43.16981132075472

O el uso de variables y el cálculo de expresiones simples:

 MathExpression expr = new MathExpression("r=3;P=2*pi*r;"); 
System.out.println("result: " + expr.getValue("P"));

O el uso de las funciones:

MathExpression expr = new MathExpression("f(x)=39*sin(x^2)+x^3*cos(x);f(3)"); 
System.out.println("result: " + expr.solve());

result: -10.65717648378352

O para evaluar la derivada en un punto dado(Nota no simbólico de la diferenciación(no numérica) detrás de las escenas, así que la precisión no está limitada por los errores de aproximaciones numéricas):

MathExpression expr = new MathExpression("f(x)=x^3*ln(x); diff(f,3,1)"); 
System.out.println("result: " + expr.solve());

 result: 38.66253179403897

Que diferencia x^3 * ln(x) una vez en x=3.El número de veces que se puede diferenciar es de 1 por ahora.

o por Integración Numérica:

MathExpression expr = new MathExpression("f(x)=2*x; intg(f,1,3)"); 
System.out.println("result: " + expr.solve());

result: 7.999999999998261... approx: 8

Este analizador es decentemente rápido y tiene un montón de otras funciones.

El trabajo ha sido concluido en portarlo a Swift a través de enlaces a C Objetivo y lo hemos utilizado en aplicaciones de gráficos entre otras iterativo de casos de uso.

DESCARGO de responsabilidad:ParserNG está escrito por mí.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top