Interpolation und
NewtonInterpolation, neue Klassen LinearerSpline
und LineareSplineInterpolation
f interpoliert
werden soll und dass somit die InterpolationsFunktion eine
"Ersatzfunktion" für f wird, erfasst werden. Bei der
Polynominterpolation kommen hierdurch die T-Knoten ins Spiel. Ferner gibt
es einen Sinn, von einer Interpolationsfehlerfunktion zu reden.
Dazu wird die abstrakte Klasse Interpolation um ein
Attribut in Form eines Objekts namens
zuInterpolierendeFunktion der Klasse Funktion
erweitert. Ein zweiter Konstruktor (sowohl in der Klasse
Interpolation als auch in deren Unterklasse
NewtonInterpolation) muss her, der dieses Objekt
übergibt und zu gegebenen Knoten die (Interpolations-)Werte durch
Funktionsauswertung berechnet.
Für die grafische Darstellung einer solchen Interpolation bieten
sich zwei Grafikfenster an: in dem ersten werden die beiden
Graphen der Funktionen zuInterpolierendeFunktion und
InterpolationsFunktion sowie die Interpolationspunkte, in
einem zweiten Fenster der Graph der Interpolationsfehlerfunktion
sowie die Knoten auf der x-Achse gezeigt. Zu diesem Zweck soll eine
neue (öffentliche) Methode Zeichne() der Klasse
Interpolation hinzugefügt werden. Um aber auch den
einfacheren Fall zu erfassen, dass nur Interpolationspunkte gegeben
sind, zu denen eine Interpolationsfunktion berechnet werden soll,
kann man eine Variable vom Typ boolean als Attribut in
der Klasse Interpolation einführen, etwa mit dem
Bezeichner FunktionsInterpolation.
Der Vorteil des OOP macht sich hier ganz deutlich bezahlt, wenn man
eine andere Interpolation als die Polynominterpolation verwendet. Dies
ist das Ziel des Teils 2 der Projektaufgabe 1: An die Stelle der Klasse
NewtonInterpolation tritt die Klasse
LineareSplineInterpolation, die das Objekt namens
InterpolationsFunktion in ihrem Konstruktor völlig
analog zu dem von NewtonInterpolation berechnet, nur,
dass an die Stelle der Zeilen
die einfachere Zeiledouble[] c = DividierteDifferenzen(); InterpolationsFunktion = new NewtonPolynom(x,c);
tritt, wobei die KlasseInterpolationsFunktion= new LinearerSpline(x,y);
LinearerSpline eine Unterklasse
von Funktion ist, deren Methode getY()
natürlich vernünftig implementiert werden muss.
Sind x[] gegebene Knoten und f eine zu
interpolierende Funktion, so kann man in einer Applikationsklasse
durch
die Polynominterpolation und durchNewtonInterpolation NIP = new NewtonInterpolation(x,f); NIP.Zeichne();
die lineare Splineinterpolation visualisieren. Ist das nicht eine großartige Anwendung des Vererbungsprinzips des OOP? Später kann auch eineLineareSplineInterpolation SIP = new LineareSplineInterpolation(x,f); SIP.Zeichne();
kubischeSplineInterpolation hinzukommen.
Kubische Splines
double[] t), die Werte (double[]
f)) und die "Steigungen" (double[] s, Ableitungen
von S an den Knoten) gegeben. Dann ist es nur noch ein kleiner Schritt
zur
public class kubischerSpline extends Funktion{
private double[] t, f, s; //Knoten, Werte, Ableitungen
public kubischerSpline(double[] x, double[] y, double[] s){
super(x[0],x[x.length-1]);
t=x; f=y; this.s=s;
}
public double getY(double x){
/*1.Bestimme j mit t[j]<=x<=t[j+1]
2.Werte das durch t[j],f[j],s[j],t[j+1],f[j+1],s[j+1] gegebene
kubische Hermite-Interpolationpolynom aus.*/
}//Ende getY
}//Ende class kubischerSpline
Will man eine Interpolationsaufgabe zu den Interpolationspunkten
(t[],f[]) lösen, so wissen wir von der Theorie, dass dies durch
einen 2-glatten kubischen Spline gelingt, wobei sogar noch zwei
Bedingungen frei sind. In jedem Fall muss ein lineares
Gleichungssystem mit den Unbekanntes s[] gelöst werden. Wie dies
geht, wird bis zum Kapitel "Lineare Gleichungssysteme"
aufgeschoben. Klar ist nur schon jetzt, wie vorgegnagen werden muss:
public class kubischeSplineInterpolation extends Interpolation{
/* Der Konstruktor %uuml;bergibt die Interpolationspunkte
double[] x, double[] y (Daten der Klasse
Interpolation), die Festlegung der zwei offenen
Bedingungen sowie evtl. eine
zuInterpolierendeFunktion. Gegebenenfalls sind mehrere
verschiedene Konstruktoren vorzusehen. Innerhalb der Konstruktoren
wird mit Hilfe einer späteren Klasse Matrix das
zugehörige lineare Gleichungssystem für die s[]
gelöst und mittels */
InterpolationsFunktion k =new kubischerSpline(t,f,s);
//berechnet.
Danach ist es ein leichtes, die Klasse NumAnalysis um
einige Methoden namens SplineInterpolation() zu
bereichern.
Java-Fallen
Ein häufiger verhängsnisvoller Fehler tritt bei Objekten
derselben Klasse mit unterschiedlichen Namen - sagen wir A1 und A2 -
auf, wenn man A1 schon allokiert hat und mittels A2=A1
eine Kopie anlegen will. Wenn danach A2 verändert wird, so
wird A1 in einem Zug mitverändert, meist ungewollt. Dies liegt
daran, dass A1 und A2 Zeiger- oder Referenzvariable sind, die ab dem
Befehl A2=A1 auf denselben Speicherbereich zeigen. Alle
Änderungen von A1 oder A2 finden in diesem Speicherbereich
statt. BeispieL:
double[] x={1,2,3};
double[] y;
y=x;
y[1]=x[1]/2; x[1]*=3;
//jetzt gilt x[1]=3=y[1]!! s. Klausuraufgabe
Will man wirklich eine Kopie anlegen, so kommt die Methode
clone() der obersten Klasse object
zum Zuge: A2=(Klassennamen) A1.clone(), oder an
unserem Beispiel: y=(double[]) x.clone();.
Eine am Anfang mysteriöse Laufzeit-Fehlermeldung lautet
NullPointerException. Diese Meldung tritt immer
dann auf, wenn Objekte nur deklariert, aber nicht allokiert sind (ihre
Variablen sind dann NullPointer, sie zeigen auf
Null), man jedoch auf ihre Komponenten zugreifen
will. Z.B. bei einem Feld, das durch double[] x;
deklariert wurde und auf das später etwa durch ... x[2]
... zugegriffen wird.
Ein weiterer häfiger Fehler entsteht bei der Division von
int-Zahlen:
int i=3; int j=5; double x=i/j; //liefert x=0 double y=j/i; //liefert y=1 //richtig: double x= (double) i/j; //Casting