/* Dreigl.java
* Autor: Markus Raab
* Datum: Freitag Okt 22
* Kategorie: Mathematik*/
/* Ein lineares inhomogenes Gleichungssystem von drei Gleichungen in
* drei Unbekannten soll gelöst werden.*/
import eprog.EprogException;
import eprog.EprogIO;
class Dreigl
{
static private float [] feld;
static private float [] ergebnis;
/* Liest ein Array von Zahlen ein:
* a11*x1 + a12*x2 + a13*x3 = b1
* a21*x1 + a22*x2 + a23*x3 = b2
* a31*x1 + a32*x2 + a33*x3 = b3
*
* feld[0] *x1 + feld[1] *x2 + feld[2] *x3 = feld[3]
* feld[4] *x1 + feld[5] *x2 + feld[6] *x3 = feld[7]
* feld[8] *x1 + feld[9] *x2 + feld[10]*x3 = feld[11]
*
* Es werden also zwölf Ganzzahlen
* (in Java auch unter Integer bekannt)
* eingelesen.*/
static private void einlesen ()
{
int i;
int j;
float temp;
boolean c = false;
try {
for (i=0; i< 12; i++)
{
EprogException sizeError = new EprogException();
feld [i] = (float) EprogIO.readInt ();
if (feld[i] > 20) throw sizeError;
if (feld[i] < -20) throw sizeError;
}
} catch (EprogException e)
{
EprogIO.println ("?");
System.exit (0); // beende Programm
}
/* Division durch Null abfangen.
* In der Diagonale müssen Werte ungleich
* Null stehen!
* Durch austauschen der Zeilen muss eine
* Möglichkeit gefunden werden, sonst wird
* FALSCHE EINGABE zurückgegeben.*/
/* Hier werden die 6 Möglichkeiten durchprobiert.
* Es werden immer abwechselt die unteren zwei Zeilen
* und dann die letzte und erste Zeile getauscht.
* Damit werden alle Möglichkeiten durchprobiert!
*
* Diese Reihenfolge demonstriert wie der Code
* funktioniert.
* a,b,c sind jeweils eine Zeile.
* a a b b c c
* b -> c -> c -> a -> a -> b
* c b a c b a
*/
for (i=1; i <= 6;i++)
{
// feld_ausgeben();
if (! (feld[0] == 0 || feld[5] == 0 || feld[10] == 0))
{
c = true;
break; // Lösung gefunden!
}
if (i%2 == 1) // Vertausche untere zwei Zeilen
{
for (j=4; j<8; j++)
{ // Vertausche j und j+4
temp = feld [j];
feld [j] = feld [j+4];
feld [j+4] = temp;
}
} else { // Vertausche oberstes und unterste Zeilen
for (j=0; j<4; j++)
{ // Vertausche j und j+8
temp = feld [j];
feld [j] = feld [j+8];
feld [j+8] = temp;
}
}
}
if (! c) // konnte keine eindeutige Lösung finden!
{
EprogIO.println ("FALSCHE EINGABE");
System.exit (0);
}
}
/* Diese Methode können Sie verwenden, um
* das Beispiel besser zu verstehen. Es gibt
* das ganze Feld schön formatiert aus.
*
* Diese Methode wurde öfters verwendet,
* musste aber auskommentiert werden, um
* die richtigen IO/Paare zu erzeugen.*/
static private void feld_ausgeben ()
{
for (int i=0; i< 12; i++)
{
EprogIO.print (feld [i]);
if (i%4 < 3) EprogIO.print ("*x" + i%4);
if (i%4 == 2) EprogIO.print (" = ");
if (i%4 < 2) EprogIO.print (" + ");
if (i%4 == 3) EprogIO.println();
}
EprogIO.println();
}
static private void ergebnis_ausgeben()
{
for (int i=0; i< 3; i++)
{
EprogIO.printFixed (ergebnis[i]);
if (i != 2) EprogIO.print (" ");
}
EprogIO.println();
}
/* Es gibt verschiedene Wege, ein Gleichungssystem zu
* berechnen eine davon ist das Gauss'sche
* Eliminationsverfahren, das hier beschrieben werden soll:
*
* Bringen Sie zuerst die Matrix [a11..a33] in Halbdiagonalform,
* das heißt, es sollen unter der Diagonale a11 a22 a33 nur noch
* Nullen stehen.
* In der Diagonale müssen Werte ungleich 0 stehen!
*
* Beispiel:
* 1 2 3 4
* 2 2 4 5 | -(2/1)*Zeile1
* 1 -1 1 7 | -(1/1)*Zeile1
*
*
* 1 2 3 4
* 0 -2 -2 -3
* 0 -3 -2 3 | -(-3/-2)*Zeile2
*
*
* 1 2 3 4
* 0 -2 -2 -3
* 0 0 1 7.5
*/
static private void halb_diagonal_form ()
{
int i;
/* Die einzelnen Zeilen werden um diesen Faktor
* erweitert, damit man auf das Ergebnis kommt.*/
float faktor;
// erster Schritt: -(2/1) * Zeile1
faktor = feld [4] / feld [0];
for (i=0; i< 4; i++)
feld [i+4] -= faktor * feld [i];
// feld_ausgeben();
// zweiter Schritt: -(1/1) * Zeile1
faktor = feld [8] / feld [0];
for (i=0; i< 4; i++)
feld [i+8] -= faktor * feld [i];
// feld_ausgeben();
// dritter Schritt: -(-3/-2) * Zeile2
faktor = feld [9] / feld [5];
for (i=0; i< 4; i++)
feld [i+8] -= faktor * feld [i+4];
// feld_ausgeben();
}
/* Wenn das Gleichungssystem auf die richtige Form gebracht
* wurde, ist die Berechnung von x1, x2 und x3
* (in diesem Fall jetzt ergebnis[0], ergebnis[1] und
* ergebnis[2]) ein Kinderspiel!
*
* feld[0] *x1 + feld[1] *x2 + feld[2] *x3 = feld[3]
* feld[5] *x2 + feld[6] *x3 = feld[7]
* feld[10] *x3 = feld[11]
*/
static private void berechnen ()
{
/* Auch hier könnte noch eine division durch Null
* auftreten, falls durch das bringen in die
* Halbdiagonalform noch ein zusätlicher Wert
* Null geworden ist?
*
* Richtig wäre ein erneuter Aufruf von Austauschen
* der Zeilen und in halbdiagonale bringen, ist
* so aber nicht gefordert.*/
if (feld[0] == 0 || feld[5] == 0 || feld[10] == 0)
{
EprogIO.println ("FALSCHE EINGABE");
System.exit (0); // beende Programm
}
/* x3 können wir direkt in der dritten Zeile
* berechnen!*/
ergebnis[2] = feld [11] / feld [10];
/* x2 können wir mit verwendung von x3 in der
* zweiten Zeile berechnen. Dazu feld[6] *x3
* subtrahieren und das ganze diviert durch feld[5]
* um zu x2 zu gelangen.*/
ergebnis[1] = (feld [7] - feld [6] * ergebnis [2])
/ feld[5];
/* Fast fertig berechnet, jetzt fehlt nur noch x1,
* welches durch die erste Zeile berechnet werden kann.
* Diesesmal den ganzen Ausdruck
* (feld[1] * x2 + feld[2] * x3)
* mit Subtraktion auf die rechte Seite bringen und
* das Ganze durch feld[0] um auf x1 zu kommen!*/
ergebnis[0] = (feld[3] -
(feld[1] * ergebnis[1] + feld[2] * ergebnis[2]))
/ feld [0];
}
static public void main (String [] arg)
{
feld = new float [12];
ergebnis = new float [3];
einlesen ();
// feld_ausgeben();
halb_diagonal_form();
berechnen();
ergebnis_ausgeben();
}
};