Domanda

Vorrei sapere se qualcuno ha informazioni o esperienza su come fare qualcosa che sembra semplice, ma non sembra che quando si cerca di programmarlo. L'idea è: invia una stringa contenente un'equazione, ad esempio: "2 * x = 10" per esempio (questo è semplice, ma potrebbe diventare molto complessa, come sqrt (54) * 35 = x ^ 2, e così via ....) e il programma sarebbe tornato x = 5 ed eventualmente dare un log di come ci fosse arrivato.

E 'questo fattibile? Se è così, qualcuno ha un vantaggio? Per info c'è questo sito ( http://www.numberempire.com/equationsolver.php ), che fa la stessa cosa in PHP, ma non è open source.

Grazie per qualsiasi aiuto!

È stato utile?

Soluzione

Questo si chiama "parsing", e anche se l'informatica ha già risolto questo problema non è semplice a tutti fino a comprendere a fondo. C'è un'intera disciplina informatica-scienza che descrive come risolvere questo problema. In C è necessario definire la grammatica del vostro input (possibilmente con regole di precedenza in esso), quindi eseguire analisi lessicale il vostro input, allora parse il risultato e, infine, valutare il vostro parse albero.

In linguaggi come Ruby, però, perché si dispone di tale supporto completo per la manipolazione di stringhe e perché avete tale potere runtime tremendo è possibile risolvere il problema con una sola riga di codice in questo modo:

puts(eval($_)) while gets

Sì, che coprirà più di quello che chiedi.

Altri suggerimenti

In primo luogo è necessario definire correttamente quali tipi di equazioni si può avere come input. Poi si dovrebbe creare una buona astrazione per rappresentare l'equazione, ad esempio, una classe polinomiale. Quando si desidera utilizzare un'espressione più complessa, andare a fare un albero per le espressioni numeriche. Analisi può essere abbastanza facile se si dispone di buone regole per convertire l'espressione in notazione prefisso, allora la valutazione è facile grazie pile. Una volta che avete alberi artithmetic o polinomi, è possibile implementare trasformazioni per calcolare la variabile (s).

Se le equazioni si ottiene complesso, Non sarà sicuramente poche righe di codice C / C ++.

Per le equazioni lineari, si dovrebbe simulare uno dei metodi descritti in Linear Algebra Books. Il codice di questo è abbastanza piccolo.

Si potrebbe provare il collegamento in SymPy al tuo C (o C ++) codice e utilizzarlo per risolvere i vostri equazioni.

IIRC, SymPy ha quel tipo di funzionalità. Inoltre, dovrebbe essere più facile da manipolare la stringa di input per un'equazione all'interno utilizzabile della Python e quindi farlo passare per SymPy per risolvere.

Non ci sarà due parti per il vostro problema: l'analisi del equazione (s), e risolverli simbolicamente. Non ho intenzione di dire molto circa la prima, dal momento che le altre risposte hanno già coperto bene che argomento; Il mio consiglio personale sarebbe quello di scrivere un semplice parser discesa ricorsiva per le espressioni in notazione del prefisso.

La seconda parte, risolvere equazioni analiticamente, sta per essere difficile. In generale ci sono classi speciali di equazioni per le quali esistono metodi standard per trovare una soluzione analitica:

  • Sistemi di equazioni lineari: ogni solutore lineare diretto. Se si desidera mostrare i passi in modo esplicito e il numero di equazioni / incognite è piccolo, io consiglierei qualcosa di semplice come eliminazione di Gauss pivot o la regola di Cramer.
  • Sistema di equazioni polinomiali: equivalenti, dopo la sostituzione di variabile, per trovare radici di singoli polinomi. Se questi hanno gradi <= 4, ci sono formule per soluzioni esatte. NB: Per gradi 3 e 4 queste formule non sono piacevoli
  • .
  • soluzioni razionali per un sistema di equazioni polinomiali con coefficiente razionale: Do variabile di sostituzione come sopra. Poi la forza bruta con il test a zero razionale.
  • Altri tipi di equazioni: Buona fortuna. Per più complicato [sistemi di] non lineari equazioni, se è possibile accontentarsi di soluzioni numeriche (non analitiche), esaminare il metodo di Newton.

Una correzione: questo non è lineare, che di solito significa da matrici di equazioni multiple e incognite

.

Il tuo esempio non è certamente complesso.

Quello che vi serve è una semplice grammatica espressione e parser. Analizzare l'equazione in un albero di sintassi astratta e camminare l'albero per valutarla.

Se si stesse scrivendo Java potrebbe apparire come questo . Un altro esempio è symja . Forse sarà abbastanza ispirazione per voi a venire con il proprio per C ++.

Si potrebbe anche voler guardare in Mathematica e Alpha di Wolfram. Stephen Wolfram è uno dei migliori matematici del mondo e gli scienziati informatici. Ha un sacco di cose che si potrebbe riutilizzare a buon vantaggio piuttosto che scrivere da soli.

Si dovrà definire cosa si intende per "risolvere" e che cosa ci si aspetta di essere tornato.

Ci sono soluzioni simboliche e soluzioni numeriche. A quale ti riferisci? Entrambi sono ugualmente validi, ma sono diversi. Potrai applicare tecniche diverse a seconda della risposta.

Un altro punto: ci sono molte tecniche per "risolvere" equazioni che dipendono molto dal tipo di equazione. Se mi dai qualcosa come f(x) = 0 penso di algoritmi che trovano radice come il metodo di Newton. Se tu mi dai una equazione differenziale ordinaria potrei provare un metodo di sostituzione o di integrazione numerica utilizzando Runge-Kutta. Se mi date un'equazione differenziale alle derivate parziali posso applicare differenze finite, elementi finiti, o tecniche di elementi di contorno. (Non fatemi parlare su ellittica, parabolica, e PDE iperboliche.)

Il punto è che la tua domanda è molto generica, e la risposta dipende molto da quello che stai cercando di fare. Maggiori dettagli potrebbero aiutare.

In generale, si dovrà analizzare l'espressione in qualche rappresentazione interna. Molti libri di algebra lineare suggeriscono di usare matrici (o std::vector) per rappresentare i coefficienti. L'esponente del termine è definito dalla sua posizione nel vettore.

Così, per esempio, l'espressione:

 2 + 3x + 5x^2

Può essere rappresentato come una matrice o std::vector:

std::vector<int> expression;
expression[0] = 2; // 2 * x ^ 0
expression[1] = 3;
expression[2] = 5;

Scrivere una funzione di valutazione diventa banale, e lasciato come esercizio per il lettore.

Risoluzione di equazioni multiple diventa più complessa. Ci sono librerie esistenti e algoritmi per questo. Una ricerca su Google dovrebbe venire con qualcosa di buono. : -)

Suggerisco a partire con termini semplici e la costruzione di un parser per questo. Una volta che le opere, è possibile modificare il parser ad accettare i nomi delle funzioni pure.

Se si sta tentando di semplificare un'espressione che ha termini su entrambi i lati del =, basta scrivere giù per le scale che normalmente prendere quando risolvere a mano. Provare alcune equazioni differenti per ottenere alcune regole in giù. Ora attuare queste regole in C ++.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top