Pergunta

O que é a forma mais inteligente para projetar um analisador de matemática? O que quero dizer é uma função que recebe uma string de matemática (como: "2 + 3/2 + (2 * 5)") e retorna o valor calculado? Eu escrevi um em VB6 há séculos, mas acabou sendo maneira de inchado e não muito portátil (ou inteligente para essa matéria ...). ideias gerais, código pseudo ou código real é apreciado.

Foi útil?

Solução

Uma abordagem muito bom envolveria duas etapas. O primeiro passo envolve a conversão de href="http://scriptasylum.com/tutorials/infix_postfix/algorithms/infix-postfix/index.htm" a expressão de infixa para sufixo (p.ex. via de Dijkstra desvio quintal ) notação. Uma vez feito isso, é bastante trivial para escrever um postfix avaliador .

Outras dicas

Eu escrevi alguns posts sobre a criação de um analisador de matemática. Há um general introdução , conhecimentos básicos sobre gramáticas , implementação de exemplo escrito em ruby ?? e uma conjunto de testes . Talvez você vai encontrar esses materiais úteis.

Você tem um par de abordagens. Você poderia gerar código dinâmico e executá-lo, a fim de obter a resposta sem a necessidade de escrever muito código. Faça uma pesquisa sobre o código gerado em tempo de execução em .NET e há uma abundância de exemplos ao redor.

Como alternativa, você pode criar um analisador real e gerar um pouco árvore de análise que é então utilizado para avaliar a expressão. Novamente, isto é bastante simples para expressões básicas. Confira codeplex como eu acredito que eles têm um analisador de matemática lá. Ou apenas olhar para cima BNF que incluirá exemplos. Qualquer site introduzindo conceitos de compilador irá incluir isso como um exemplo básico.

Codeplex avaliador de expressão

Eu sei que isso é velho, mas me deparei com esta tentando desenvolver uma calculadora como parte de um aplicativo maior e correu alguns problemas usando a resposta aceita. As ligações eram imensamente útil para compreender e resolver este problema e não devem ser descontados. Eu estava escrevendo um app Android em Java e para cada item na expressão "string", eu realmente armazenada uma String em um ArrayList como o usuário digita no teclado. Para a conversão infixa-a-sufixo, eu iterado cada corda no ArrayList, em seguida, avaliada a ArrayList sufixo rearranjadas de cordas. Este foi fantástica para um pequeno número de operandos / operadores, mas os cálculos mais longos foram consistentemente fora, especialmente porque as expressões começou avaliando a não-inteiros. No link fornecido para Infix para Postfix conversão , sugere popping a pilha se o item digitalizado é um operador e o item topStack tem uma precedência maior. Descobri que isso é quase correta. Popping o item topStack se de precedência é maior ou igual ao operador digitalizada finalmente fez meus cálculos sair correta. Esperemos que isto vai ajudar alguém a trabalhar sobre este problema, e graças à Justin Poliey (e fas?) Para a prestação de alguns links de valor inestimável.

Se você tem um "always on" aplicativo, basta postar a string de matemática ao google e analisar o resultado. maneira simples, mas não tenho certeza se é isso que você precisa -. mas inteligente, de alguma forma eu acho

A questão relacionada Equação analisador (expressão) com precedência? tem alguma informação boa sobre como começar com isso também.

-Adam

Assumindo que sua entrada é uma expressão infix no formato de cadeia, você pode convertê-lo para postfix e, utilizando um par de pilhas: uma pilha de operador e uma pilha de operandos, trabalhar a solução a partir daí. Você pode encontrar informações gerais algoritmo no link Wikipedia.

ANTLR é um gerador de analisador muito agradável LL (*). Eu recomendo.

Os desenvolvedores sempre quer ter uma abordagem limpa e tentar implementar a lógica de análise de baixo para cima, geralmente terminando com o Dijkstra manobras-Yard Algoritmo . Resultado é puro código procurando, mas possivelmente montado com bugs. Eu desenvolvi uma tal API, JMEP , que faz tudo isso, mas ele me levou anos para tem o código estável.

Mesmo com todo esse trabalho, você pode ver, mesmo a partir dessa página projeto que estou seriamente considerando a possibilidade de passar a usar JavaCC ou ANTLR, mesmo depois de todo esse trabalho já feito.

11 anos no futuro a partir de quando foi feito esta pergunta: Se você não quer re-inventar a roda, há muitos analisadores de matemática exótica lá fora.

Há um que eu escrevi anos atrás que suporta operações aritméticas, resolução de equações, cálculo diferencial, cálculo integral, estatísticas básicas, função / definição fórmula, gráficos, etc.

Seu chamado ParserNG e sua livre.

Ao avaliar uma expressão é tão simples como:

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

    result: 43.16981132075472

Ou usando variáveis ??e cálculo de expressões simples:

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

Ou usando funções:

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

Ou para avaliar a derivada em um determinado ponto (Nota faz diferenciação simbólica (não numérica) nos bastidores, de modo a precisão não é limitado pelos erros de aproximações 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) uma vez em x = 3. O número de vezes que você pode diferenciar é de 1 para agora.

ou para Integração 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 analisador é decentemente rápido e tem muitas outras funcionalidades.

O trabalho foi concluído em portá-la para Swift via ligações para Objective C e nós tê-lo usado em gráficos de aplicativos entre outros casos de uso iterativos.

IMPORTANTE: ParserNG é de autoria de me

.
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top