Was ist die Newton-Interpolation ?Bei der Newton-Interpolation sucht man zu n Funktionswerten (x, y) ein Polynom, welches genau durch diese Punkte geht. Dafür braucht man ein Polynom, welches höchstens vom Grad (n-1) ist. Die Newton-Interpolation liefert ein Polynom, welches zu jedem der n x-Werte genau den passenden y-Wert liefert. Dies ist allerdings noch ohne Wert, denn was will man mit Werten, die man schon kennt? Die Interpolation wird gerne eingesetzt, um Zwischenwerte aus Tabellen zu berechnen. Wer noch Logarithmentafeln aus seiner Schulzeit kennt, weiß, dass man Zwischenwerte, die nicht in der Tabelle standen, mit der linearen Interpolation berechnen mußte. Eine Schlangenlinie in der Tabelle deutete manchmal auch an, dass die lineare Interpolation nicht genau genug war. Auch heute noch gibt es viele Zusammenhänge, die nicht ganz zu durchschauen sind, so dass man Tabellen verwendet, um Zwischenwerte daraus zu berechnen, so manche Steuerung (z.B. für Heizkessel, ESP) benutzt heimlich Tabellen und interpoliert dann die Zwischenwerte. Die Newton-Interpolation ist relativ schnell und einfach durchzuführen, in mathematischen Lehrbüchern wird aber auch gerne das Lagrange-Verfahren zur Interpolation angegeben, welches aber rechnerisch viel aufwändiger ist. |
Seit einigen Versionen bietet VBA Klassenmodule an. Dieses Beispiel soll zeigen, wie man Klassenmodule sinnvoll einsetzen kann.
Hier geht es darum, dass mit den gleichen Funktionen mehrere verschiedene Datenquellen bearbeiten möchte, wobei sich die Programme ihre Daten nicht gegenseitig überschreiben dürfen. Weil die Aufgabe und ihre Lösung nicht offensichtlich ist, habe ich die Newton-Interpolation als praktisches Beispiel vorbereitet.
Nehmen wir an, wir haben einen Versuch gemacht und eine Tabelle mit Messwerten vorliegen. Da wurde in unterschiedlichen Zeitabständen eine Kraft F gemessen, aber leider ist der formelmässige Zusammenhang zwischen Zeit und Kraft gegenwärtig unbekannt. Andererseits müssen Kräfte nachträglich auch für Zeitpunkte ermittelt werden, die nicht in der Tabelle stehen, also wo gar keine Kraft gemessen wurde.
Zeit [s] | 1 | 2 | 3 | 4 |
---|---|---|---|---|
Kraft [N] | 1 | 4 | 9 | 16 |
Nehmen wir dazu die links dargestellte, einfache Tabelle, in der die Kraft (F) und die Zeit (t) gegeben ist: Es ist offensichtlich, dass hinter diesem Beispiel die Formel F(t) = c · t2 steckt - wollen wir doch einmal sehen, ob das die Mathematik und der Computer auch feststellen. Die Aufgabe besteht nun darin, die Kraft F zum Zeitpunkt t = 1.5, also F(1.5) zu ermitteln. Dazu brauchen wir zunächst ein VBA-Programm, welches in einem (normalen) Standardmodul so aussehen würde:
' Die Funktion untersucht die übergebenen Arrays
und ermittelt
|
Um das Programm zur Interpolation aus einem anderen Programm heraus aufzurufen, um den Wert von F(1.5) zu ermitteln, würde man so vorgehen:
Sub TestAufruf()
|
Die Dialogbox zeigt den korrekten Wert 2.25 an.
Soweit, so gut. Aber was macht man, wenn man auch noch F(2.5) und F(3.5)
ermitteln will ? Bei jedem Aufruf von Interpolation()
wird die ganze Berechnung
komplett neu durchgeführt, obwohl die doppelte FOR
-Schleife am Anfang
des Programms nur einmal durchlaufen werden muß - dann hat man den
größten Teil der Arbeit erledigt und kommt mit der letzten
FOR
-Schleife aus, weil nur noch ein neuer Wert ermittelt werden muss.
Offensichtlich wäre es also günstiger, zwei Programme zu schreiben:
Das folgende Beispiel zeigt die Lösung mit den Programmen
InitInterpolation()
, Interpolation2()
und den auf Modulebene
als privat deklarierten Variablen X
und Y
.
Private X, Y
|
Der Aufruf von einem anderen Programm aus funktioniert dann so:
Sub TestAufruf()
|
Doch es bleibt immer noch ein Problem: Was passiert, wenn man gleichzeitig mit zwei unterschiedlichen Tabellen arbeiten muss? Nehmen wir den Fall an, daß wir eine zweite Tabelle haben, in der der Weg (s) und die Zeit (t) angegeben ist:
Zeit [s] | 2 | 3 | 5 | 11 |
---|---|---|---|---|
Weg [m] | 3 | 8 | 24 | 120 |
Auch hier ist offensichtlich, dass hinter diesem Beispiel die Formel s(t) = c ·( t2 - 1) steckt, aber als Beispiel reicht es aus. Was passiert, wenn wir abwechselnd eine Interpolation für F(t) und dann wieder für s(t) einen Wert berechnen will?
Nun bei jedem Wechsel von
F(t) auf s(t) muß man InitInterpolation()
neu aufrufen, der rechnerischer Aufwand bleibt hoch. Außerdem
darf man keinen anderen Programmteil aufrufen, der die Interpolation zwischendurch
zusätzlich für eigene Zwecke benutzen könnte, weil sonst die globalen
Variablen X
und Y
geändert werden!
Das Klassenmodul |
Die beste Lösung bietet hier ein Klassenmodul, welches als neues Modulblatt im VBA-Editor (der VBE) eingefügt wird. Ein Klassenmodul kann nämlich beliebig oft aufgerufen werden und jedesmal ist es so, als ob man die Funktionen zur Interpolation noch einmal auf einem weiteren Modulblatt programmiert hätte - die Instanzen (= aufgerufenenKlassenmodule) stören sich nicht und verhindern den Zugriff auf ihre Daten von außen. < /P>
Zunächst muß man ein eigenes (Klassen-)Modulblatt anlegen und ganz für die Newton-Interpolation reservieren:
Option Explicit
|
Wichtig ist auch, dass das Klassenmodul einen vernünftigen Namen bekommt,
denn unter dem wird es aus anderen Anwendungen heraus angesprochen. Hier
soll 'NewtonInterpolation
' gewählt werden. Über die
Property Let
-Prozeduren nimmt das Klassenmodul die Arrays()
mit den x- und y-Werten entgegen und speichert sie intern in den Variablen
X und Y auf (Klassen-)Modulebene. Da es keine Property Get
-Prozeduren gibt,
kommt man später auch nicht mehr an die Inhalte von X und Y heran -
das ist der Unterschied zwischen Eigenschaften (den Variablen von Klassenmodulen)
und echten Variablen: Nach dem Rückruf können die Daten völlig
anders aussehen (oder gar nicht mehr gesehen werden), als vor dem Speichern.
Um festzustellen, ob die Hauptarbeit der Interpolation für die Daten
schon einmal ausgeführt wurden, benutzt das Klassenmodul die Variable
IstBerechnet
, die über True/False die Berechnung steuert.
Die Klasse im Einsatz |
Will man nur eine einzige Interpolation ausführen, hilft die
With
-Anweisung mit dem Schlüsselwort New
:
Public Sub TestKlasse()
|
An dem Beispiel sieht man, warum ein aussagefähiger Name für das Klasenmodul wichtig ist.
Bei der Eingabe merkt man ausserdem, daß 'IntelliSense' bei der Eingabe hilft und die Namen
der Eigenschaften und Methoden der Klasse NewtonInterpolation
kennt.
Will man mehrere Interpolationen durchführen, empfiehlt sich die Verwendung einer
Objekt-Variablen, die vom Typ Object
oder besser NewtonInterpolation
ist.
Public Sub TestKlasse()
|
Will man mehrere verschiedene Interpolationen verwenden, so kann man auch mehrere Variable mit unterschiedlichen Instanzen des Klassenmoduls erzeugen:
Public Sub TestKlasse()
|
Wie man sieht, kann man mit Tabelle1
und Tabelle2
zwei
Berechnungen beliebig durcheinander laufen lassen - ohne dass sich die
Instanzen des Klassenmoduls gegenseitig die Daten überschreiben.
Das Beispiel zeigt auch eine zweite Variante, Variable zu deklarieren: Wird das Schlüsselwort
New
bereits in der Dim
-Anweisung verwendet, kann man sich
das spätere Set
ersparen.