Il logo di batmath
www.batmath.it

Giochiamo con Gauss

Questo codice è pubblicato anche su http://ww2.unime.it/weblab/ita/Gauss/index.html

Questo programma implementa la risoluzione di un sistema di m equazioni in n incognite, con il metodo della riduzione a scala di Gauss-Jordan. Sono proposte due versioni: nella prima è richiesto l'intervento diretto dell'utente per le varie operazioni e per la risoluzione effettiva del sistema, nella seconda la risoluzione è completamente automatica. La seconda versione è semplicemente un adattamento della prima e non prevede l'uso di un metodo ricorsivo che sarebbe il più naturale per questo tipo di problema. Come gli altri programmi proposti in questa sezione del nostro sito, lo scopo è prevalentemente didattico e non si è cercata l'ottimizzazione del codice.

Dal punto di vista matematico non ci sono particolari osservazioni da fare e quelle più importanti si possono leggere nella pagina di Help collegata alla prima versione del programma.

Il codice Javascript è stato sviluppato secondo lo schema seguente:

  1. Viene innanzitutto richiesto il numero di equazioni e di incognite del sistema. Entrambi i numeri devono essere non superiori a 10, per ridurre al minimo eventuali problemi di overflow, prevedibili in quanto l'algoritmo è scritto per utilizzare frazioni di interi e non decimali in virgola mobile. Questi problemi si presentano comunque per sistemi con molte incognite e/o equazioni e, in ogni caso, occorre verificare l'attendibilità dei risultati ottenuti. Una apposita funzione (solonum()) controlla che vengano inseriti solo numeri e non accetta altri caratteri da tastiera.
  2. Successivamente viene generata dinamicamente una maschera per l'input dei dati, con delle caselle di input per ognuno dei coefficienti e termini noti. E' anche prevista un'introduzione casuale di questi valori, nel qual caso, sempre per i citati problemi di overflow, i coefficienti sono limitati agli interi compresi tra -10 e +10. Le caselle di input (del tipo text) sono referenziate utilizzando l'array form.elements[] (in questo caso il nome del form è matrice e quindi matrice.elements[]), in cui l'indice è l'indice progressivo di numerazione degli elementi man mano che vengono generati.
  3. A questo punto l'utente può introdurre i coefficienti, nella forma numeratore/denominatore, ove numeratore e denominatore sono interi. Una  funzione (solofraz()) controlla che vengano inseriti solo caratteri adatti (numeri, eventuale segno meno, eventuale segno di frazione).
  4. Introdotti i coefficienti tutte le caselle di input vengono controllate (funzione controlla()) per verificare l'accettabilità del dato, e, se del caso, i dati vengono vengono memorizzati in una tabella (array a due indici), i cui elementi sono a loro volta array con due componenti (il numeratore e il denominatore). Poiché Javascript non prevede esplicitamente array bidimensionali, si è fatto ricorso ad un array di array, secondo la tecnica standard. Per questioni di semplicità l'eventuale segno negativo del numero può comparire solo al numeratore. Si sono introdotti anche altri due array, uno per memorizzare i dati iniziali, nel caso l'utente voglia tornare al punto di partenza, uno per memorizzare i dato prima di ogni variazione, nel caso l'utente voglia tornare indietro di un passo. Dopo l'accettazione dei dati le caselle di input vengono disabilitate alla lettura per evitare errate manipolazioni da parte dell'utente. E' comunque possibile cambiare i dati iniziali: la funzione cambiadato() fa ritornare al punto di partenza riabilitando le caselle di input.
  5. Terminata questa fase l'utente può iniziare ad operare per ridurre il sistema in forma a scala, seguendo esattamente il procedimento che si farebbe manualmente.  Quando l'utente ha terminato di operare su una riga si può scendere di livello: il codice controlla che sotto il candidato pivot di una riga ci siano solo zeri. Questa operazione è gestita da un'apposita funzione: scendi()
  6. Le operazioni di riscrittura delle caselle di input con i valori modificati, operazione che evidenzia le caselle con zeri e le caselle con i pivot, sono gestite dalla funzione riscrivi()
  7. E' sempre possibile semplificare i calcoli se i coefficienti di una riga hanno divisori comuni o se si vuole avere pivot unitari, operazione utile al momento della risoluzione del sistema.
  8. Terminate tutte le operazioni il codice può, su richiesta dell'utente, risolvere il sistema (con la funzione risolvi()) con la stessa tecnica che si usa manualmente, cioè cominciando dall'ultima riga e procedendo all'indietro: le incognite i cui coefficienti non sono pivot rimarranno indeterminate e compariranno come parametri arbitrari. Per consentire l'esecuzione di calcoli simbolici (le incognite "già trovate" e da sostituire nelle righe superiori non sono numeri, ma espressioni lineari nei parametri), la soluzione del sistema è costruita mediante un array di n elementi (tanti quante le incognite) e ciascun elemento dell'array è, a sua volta, un array contenente al posto zero il termine noto e negli altri posti i coefficienti dei parametri via via introdotti. Naturalmente gli elementi di quest'ultimo array saranno a loro volta array con due componenti, una per il numeratore e una per il denominatore.
  9. Un'ultima difficoltà da superare: la scrittura dell'output, per evitare di scrivere frazioni con denominatore uno, o di far comparire parametri con coefficiente nullo. Questo è gestito dalla funzione compatta().
  10. Numerose altre funzioni svolgono compiti particolari, per esempio la riduzione delle frazioni ai minimi termini, l'operazione di inserimento casuale dei coefficienti, la somma di array di frazioni o il prodotto di una frazione per un array di frazioni, il ritorno indietro di un passo, il ritorno al punto di partenza, ecc.

Come si vede si tratta di un codice abbastanza complesso, soprattutto per la necessità di controllare le numerose operazioni eseguite dall'utente. Il codice per la soluzione automatica è notevolmente più semplice e potrebbe essere ulteriormente semplificato, come già detto, con una implementazione ricorsiva. In ogni caso le 720 righe da cui è costituito questo script potrebbero essere ridotte eliminando alcune ripetizioni e compattando alcune funzioni. Potrebbe essere un utile esercizio per lo studente volenteroso!

Commenti:

pagina pubblicata il 01/12/2001 - ultimo aggiornamento il 01/09/2003