Universität Hamburg - Fachbereiche - Fachbereich Mathematik

Java-Kurs (3)

Numerische Mathematik, WiSe 99/00 und SoSe 00, Bodo Werner

Zurück zum Inhaltsverzeichnis.

Polynominterpolation

Die Klassen NewtonPolynom, (Newton)Interpolation (Polynominterpolation)

Zugriffsrechte (Modifier) private, public, protected von Daten und Methoden eines Objektes
Numerisches Ziel der folgenden Klassen ist es, zu gegebenen n+1 Knoten und Werten das (Newton'sche) Interpolationspolynom vom (Höchst-)Grad n zu finden. Hierzu definieren wir zunächst eine Unterklasse NewtonPolynom von Funktion1, um Polynome in der speziellen Newton'schen Darstellung zu konstruieren (und auszuwerten):
 1  public class NewtonPolynom extends Funktion1{
 2    private int Grad;
 3    private double x[]; //Knoten
 4    private double c[];
 5    //(p=c[0]+c[1]*(x-x[0])+....
            +c[n]*(x-x[0])*...*(x-x[n-1])

 6    public NewtonPolynom(double[] x, double[] c{
 7     super(); //max.Def.Bereich
 8     Grad=x.length-1;
 9     this.x=x;
10     this.c=c;
11    }//Ende Konstruktor

12    public double getY(double z){
13    double y;
14    // Ausfüllen mit Horner Schema
15    return y;
16    }//Ende getY
17  }//ende class NewtonPolynom

Das Ausfüllen von Zeile 14 wird der Übungsaufgabe 11 überlassen.

Einzige neue Java-Aspekte sind die Zugriffsrechte in Form von Modifiern. Sie dienen der Kapselung, d.h. der Abschottung gewisser Methoden und Attribute gegen Zugriffe durch andere Objekte. Durch den Zusatz private gilt eine Sichtbarkeit nur innerhalb der zugehörigen Klasse. Als guten Programmierstil gilt es, alle Daten nur durch Methoden (wie z.B. Konstruktoren) festzulegen und zu ändern. Die Daten werden daher i.a. als private oder auch, falls sie noch in Unterklassen (allgemein in Paketen (pachages)) sichtbar sein sollen, als protected gekennzeichnet. Der Modifier public signalisiert, dass von allen Klassen aus hierauf zugegriffen werden kann. Es sind die öffentlichen Methoden mit ihren Parameterlisten und ihren Rückgabewerten, die der Verbindung nach außen dienen. Natürlich sollte die Methode getY() in Zeile 12 öffentlich sein.

Will man das Newton'sche Interpolationspolynom berechnen, muss man "nur" noch die Koeffizienten double[] c mit dem Schema der Dividierten Differenzen berechnen. Danach könnte man etwa auf die Methode getWertetabelle() (Aufgabe 7) in der Klasse Funktion1 zugreifen. Dies könnte in einer Applikationsklasse geschehen. Wir wollen jedoch einen komplexeren Weg gehen, indem wir "Interpolation" durch eine abstrakte Klasse erfassen und dann die "Newtoninterpolation" durch eine Unterklasse beschreiben:

I1  public abstract class Interpolation
I2    protected int n; //Ordnung
I3    protected double[] x;//Knoten
I4    protected double[] y;//Werte
I5    protected Funktion1 InterpolationsFunktion;
I6    protected Interpolation(double[] x, double[] y){
I7      n=x.length-1;
I8      this.x=x;
I9      this.y=y;
I10   }//Ende Konstruktor
I11 }//Ende class Interpolation
Diese abstrakte Klasse hat vier Attribute, die selbsterklärend sein sollten. Dabei wird die InterpolationsFunktion bei einer Polynominterpolation ein (Newton'sches) Polynom sein, bei der späteren Splineinterpolation aber etwas anderes. Später wird diese Klasse u.a. um die grafische Methode Zeichne() erweitert.

In der Unterklasse

N1  public class NewtonInterpolation
                   extends Interpolation{
N2      public NewtonInterpolation
                   (double[] x, double[] y){
N3        super(x,y);
N4        double[] c = DividierteDifferenzen();
N5        InterpolationsFunktion = new
            NewtonPolynom(x,c);
N6      }
N7      private double[] DividierteDifferenzen(){
N8        double[] c=new double[n+1];
N9        //Ausfüllen!!
N10       return c;
N11     }//Ende DividierteDifferenzen()
N12 }
ist der Konstruktor (Zeilen N2-N6) das wichtigste, der die InterpolationsFunktion (Attribut der Klasse Interpolation) mit Hilfe der Methode DividierteDifferenzen() (auszufüllen in Aufgabe 11) als NewtonPolynom berechnet! Beachte, dass mit Hilfe von super() in Zeile N3 auf den Konstruktor der abstrakten Klasse Interpolation zugegriffen wird.

Der Modifier private ist nur dann sinnvoll, wenn sich niemand für die Koeffizienten double[] c des Newton'schen Interpolationspolynoms interessieren sollte, s. Aufgabe 12.

Jetzt sieht eine Appikationsklasse etwa so aus

B 1 class Bsp6{
B 2  static void main(String[] args){
B 3   double[] x={0 ,0.1,0.2,0.3,0.4};
B 4   double[] y={-1, 1 , 4 , 3 , 2 };
B 5   NewtonInterpolation
        NIP =new NewtonInterpolation(x,y);
B 6   double[] z =
       NIP.InterpolationsFunktion.
          getWertetabelle(0,0.5,10);
B 7   for(int i=0;i<=10;i++)
        System.out.println("z["+i+"]="+z[i]);
B 8   System.out.println();
B 9  }//Ende main()
B10 }//Ende class Bsp6

In Zeile B5 wird ein Objekt namens NIP der Klasse NewtonInterpolation geschaffen, um auf die öffentliche Methode getWertetabelle() ihrer Variable InterpolationsFunktion in der doppelten Punktnotation der Zeile B6 zuzugreifen. Der Vorteil eines solchen Vorgehens kommt aber erst dann zum Tragen, wenn man etwa in Zeile B5 später "Newton" durch "Spline" ersetzt.

Als letztes verweise ich auf die sehr einfache Deklaration der beiden Felder x und y in den Zeilen B3 und B4 - ohne Verwendung von new.

Grafische Darstellung der Interpolation

Hier kommt die Black Box zum Zeichnen von Graphen von Funktionen und einzelnen Punkten zum Tragen. Man lese sich die dortige "Bedienungsanleitung" sorgfältig durch.

Wir wollen die Wurzelfunktion in den 5 Knoten 0, 0.1,...,0.4 durch ein Polynom vom Grade 4 interpolieren und die Graphen der Wurzelfunktion und des Interpolationspolynoms sowie die 5 Interpolationspunkte darstellen.

 1  public class Bsp7{
 2   public static void main(String[] args){
 3    double[] x={0 ,0.1,0.2,0.3,0.4};//Knoten
 4    double xMin=0; double xMax=0.5;
 5    Wurzel f1 = new Wurzel(xMin,xMax);
 6    double[] y=new double[x.length];
 7    for (int i=0;i<=x.length-1;i++) y[i]=f1.getY(x[i]);
 8    NewtonInterpolation  NIP= new NewtonInterpolation(x,y);
 9    NIP.InterpolationsFunktion.setIntervall(xMin,xMax);
10    //setIntervall ist eine Methode der Klasse Funktion
11    NIP.InterpolationsFunktion.Name="IP";
12    Liste fr=new Liste(); 
13    fr.addDarstellbar(f1); 
14    fr.addDarstellbar(NIP.InterpolationsFunktion);
15    InterpolPunkte f3=new InterpolPunkte(x,y);
16    fr.addDarstellbar(f3);     
17    Grafik g=new Grafik(fr);
18   }
19  }
Hier werden die drei grafischen Darstellungen der Wurzelfunktion (Zeile 13), des Interpolationspolynoms (Zeile 14) und der Interpolationspunkte (Zeile 15) in einer Liste (Zeile 12) zusammengestellt. Die Zeile 17 ist sehr mächtig und bewirkt, dass die Zeichnung in einem Fenster zu sehen ist. Das Ergebnis sieht so aus:

Dieses Programm zeigt auch einige bemerkenswerte Dinge des OOP: NIP.InterpolationsFunktion ist ein Objekt der Klasse Newtonpolynom, welche von der Klasse Funktion (ab jetzt ersetzen wir das Provisorium Funktion1 durch Funktion) abgeleitet wird. Damit erbt NIP.InterpolationsFunktion das Attribut Name (s. Zeile 11) und die Methode setIntervall() (s. Zeile 9). Letztere dient hier dazu, den horizontalen Bereich der Grafik zu bestimmen. Beachte, dass es sich jetzt so richtig "bezahlt" macht, dass die Klasse Newtonpolynom als Unterklasse von Funktion definiert wurde. Wenn wir später LineareSplineInterpolation oder KubischeSplineInterpolation als Unterklasse von Interpolation einführen, können wir dieses Programm praktisch vollständig übernehmen: NewtonInterpolation braucht nur durch SplineInterpolation ersetzt zu werden.

Noch erstaunlicher ist jedoch die Methode addDarstellbar() des Objektes fr vom Typ Liste in den Zeilen 13, 14 und 16, weil die Parameter alle von unterschiedlichem Typ sind: die ersten beiden sind Objekte verschiedener Unterklassen von Funktion, während f3 ein Objekt vom Typ InterpolPunkte ist. Schauen wir uns zur Erklärung den Teil von Liste.java an, der sich auf diese Methode bezieht, so sehen wir, dass als Parameter von addDarstellbar() ein Objekt vom Typ Darstellbar vorgesehen ist. Darstellbar definiert ein Interface, welches in der abstrakten Klasse Funktion mittels

class Funktion implements Darstellbar
als eine Art Oberklasse angesehen werden kann. Da auch die Klasse InterpolPunkte dieses Interface implementiert, sind f1, f2, f3 alle vom Typ Darstellbar und können als Parameter von addDarstellbar() aufreten. Das nennt man Polymorphie.

Ich will das Interface-Konzept hier nicht vertiefen und verweise auf Lehrbücher.

Über die wichtigsten öffentlichen Methoden und Daten der Black-Box-Klassen gibt es eine Übersicht.

Weiter mit "Splineinterpolation"