F A C H H O C H S C H U L E W E D E L
Seminaraufgabe Pascal SS 96
Numerische Lösung von expliziten Differential-Gleichungen erster Ordnung
und grafische Darstellung der Lösungsfunktion
Programm DGL
Udo Becker
PI 6222
13. Januar 1997
Das vorliegende Programm dient zur numerischen Lösung von expliziten Differential-Gleichungen erster Ordnung. Bei einfacheren Differential-Gleichungen bietet eine analytische Lösung zwar genauere Ergebnisse, jedoch lassen sich viele Differential-Gleichungen analytisch nicht lösen. In diesen Fällen kommt nun eine numerische Lösung durch Einschrittverfahren in Betracht. Als numerische Lösung erhält man x-y-Wertepaare in Form einer Wertetabelle, die durch das Programm als Funktion grafisch dargestellt werden.
Durch ein Einschrittverfahren werden aus vorhandenen Funktionswerten nachfolgende Nährungwerte berechnet. Als Voraussetzung für die Berechnung wird also ein Paar von x-y-Werten benötigt, man spricht von einem Anfangswertproblem.
Hierbei ist für die Genauigkeit der Berechnung die Schrittweite von entscheidender Bedeutung. Bei kleinerer Schrittweite werden im Prinzip genauere Werte berechnet, jedoch müssen in einem vorgegebenem Intervall mehr Berechnungen durchgeführt werden, so daß die Rundungsfehler zunehmen. Hieraus ergibt sich die Notwendigkeit einer Schrittweitensteuereung, die in diesem Programm mit den Einbettungsformeln von England nach dem Runge-Kutta-Verfahren durchgeführt wird.
Das Programm wurde in Borland Turbo Pascal 7.01 geschrieben.
Das Hauptprogramm wurde als Turbo Vision Standard Objekt definiert, somit steht dem Benutzer eine für Turbo Vision Programme übliche Umgebung zur Verfügung. Die Bedienung kann mit der Maus oder über Tastatur erfolgen. Beim Start erscheint eine kurze Programminformation.
In der Menüleiste sind die Programmoptionen ‘Eingabe’, ‘Laden’, ‘T-Rechner’ und ‘Info’ sowie eine Uhr untergebracht. Die Statusleiste enthält Informationen über Tastaturbefehle.
Über ‘F10’ läßt sich die Menüleiste aktivieren. Die Programmoptionen könne ebenfalls mit der Tastenkombination ‘Alt+<Markierter Buchstabe>‘ aufgerufen werden. Mit der Escape-Taste lassen sich Fenster schließen.
Beendet wird das Programm mit der Tastenkombinatin ‘Alt+X’ oder mit der Maus durch anklicken von ‘Exit’.
Im Eingabefenster wird der Benutzer aufgefordert, die zu lösende Differential-Gleichung in expliziter Form einzugeben. Diese muß in der im Pascal-Quellcode üblichen Schreibweise vorliegen. Der Ausdruck ‘dy/dx =‘ ist bereits vorgegeben und darf nicht eingegeben werden. Folgende Ausdrücke sind erlaubt:
x, y | Variable |
(, ) | Klammern |
0..9 | Zahlen |
+, -, *, / | Grundrechenarten |
sin, cos, tan, arctan | trigonometrische Funktionenen |
exp | Exponentionalfunktion |
ln | natürlicher Logarithmus |
log | Logarithmus zur Basis 10 |
sqr | Quadrat |
sqrt | Quadratwurzel |
abs | Betrag |
int | ganzzahliger Anteil |
frac | nichtganzzahliger Anteil |
Erfolgt die Eingabe der Differential-Gleichung nicht in korrekter Weise wird der Benutzer durch eine Fehlermeldung aufgefordert, die Eingabe zu korrigieren.
Weiterhin müssen im Eingabefenster der x-Minimalwert, der x-Maximalwert, der y-Anfangswert sowie die Genauigkeitsschrake e eingegeben werden. In diesen Eingabefeldern werden nur Dezimalzahlen akzeptiert. Hier erfolgt ebenfalls eine Prüfung, ob korrekte Werte eingegeben wurden, die im negativen Fall eine Fehlermeldung hervorruft.
Das Eingabefenster enthält zwei Funktionsknöpfe: einen Abbruchknopf, der das Eingabefenster schließt, und einen einen Ok-Knopf, der die Berechnung und bei fehlerfreier Rechnung anschließend die Grafische Ausgabe der Funktion veranlaßt.
Fehler während der Berechnung wie z.B. Fließkommaüberläufe oder Divisionen durch Null erzeugen eine Fehlermeldung mit Angabe der entsprechenden x- und y-Werte, so daß der Benutzer den Auswertungsbereich der Funktion entsprechen anpassen kann.
Beim Öffnen des Eingabefensters werden in die Eingabefelder automatisch die Parameter der letzten Berechnung aus der Datei DGL.PAR geladen, ebenfalls werden die Parameter beim schließen des Eingabefensters in dieser Datei gespeichert.
Nach der Berechnung oder nachdem eine bereits vorhandene Datei geladen wurde erfolgt die grafische Ausgabe. Hier wird die Funktion in einem nach den Minimal- und Maximalwerten skalierten Koordinatensystem dargestellt.
Der Grafik-Bildschirm kann mit der Escape-Taste beendet werden.
Wurde eine Funktion berechnet und grafisch dargestellt wird der Benutzer gefragt, ob er die Für eine erneute Darstellung der Funktion benötigten Daten abspeichern möchte.
Für das Abspeichern der Darstellungs-Daten wird ein Turbo Vision Standard Dialog verwendet, der es dem Benutzer erlaubt, die Datei an einer beliebigen Stelle in seinem Dateisystem abzulegen. Für die zu speichernden Dateien sollte die Erweiterung ‘* .DGL’ verwendet werden, die auch vorgegeben wird.
Ist bereits eine Datei mit dem gewähltem Namen vorhanden wird gefragt, ob diese überschrieben werden soll.
Der Lade-Dialog ist ebenfalls ein Turbo Vision Standard Dialog. Der Benutzer kann sein Dateisystem nach Dateien mit der Erweiterung ‘* .DGL’ durchsuchen und diese laden. Wird eine Funktion geladen erfolgt die grafische Ausgabe.
Die Auswahl ‘T-Rechner’ gibt einen einfachen Taschenrechner aus einer Turbo Vision Standard Unit auf den Bildschirm.
Unter ‘Info’ erhält man eine kurze Programminformation.
{-------------------------------------------------------------------------} { Programm zur numerischen L”sung von expliziten Differential-Gleichungen erster Ordnung Udo Becker 1996/97 } program DGL; {$X+} {$S+} {$M 65520,8192,655360} {-------------------------------------------------------------------------} uses DGLGlob, Etc, Input, LoadSave, { Turbo Pascal Standard Units } App, Drivers, Gadgets, Memory, Menus, Objects, Views; type TDGL = object(TApplication) Clock : PClockView; Heap : PHeapView; constructor Init; procedure HandleEvent(var Event : TEvent); virtual; procedure Idle; virtual; procedure InitMenuBar; virtual; procedure InitStatusLine; virtual; end; const HeapSize = 48 * (1024 div 16); { 48k Heap } {-------------------------------------------------------------------------} { Initialisierung } constructor TDGL.Init; var R : TRect; begin MaxHeapSize := HeapSize; inherited Init; GetExtent(R); R.A.X := R.B.X - 9; R.B.Y := R.A.Y + 1; Clock := New(PClockView, Init(R)); Insert(Clock); GetExtent(R); Dec(R.B.X); R.A.X := R.B.X - 9; R.A.Y := R.B.Y - 1; Heap := New(PHeapView, Init(R)); Insert(Heap); Info; end; { Init } {-------------------------------------------------------------------------} { Auswahl der Handlungsm”glichkeiten } procedure TDGL.HandleEvent(var Event: TEvent); begin inherited HandleEvent(Event); case Event.What of evCommand: begin case Event.Command of cmEingabe : Eingabe; cmLaden : Laden; cmRechner : Rechner; cmInfo : Info; else Exit; end; ClearEvent(Event); end; end; end; { HandleEvent } {-------------------------------------------------------------------------} { Uhrzeit und Speicherbelegung aktualisieren } procedure TDGL.Idle; begin inherited Idle; Clock^.Update; Heap^.Update; end; { Idle } {-------------------------------------------------------------------------} { Menleiste } procedure TDGL.InitMenuBar; var R : TRect; begin GetExtent(R); R.B.Y := R.A.Y+1; MenuBar := New(PMenuBar, Init(R, NewMenu( NewItem('~E~ingabe', '', kbNoKey, cmEingabe, hcEingabe, NewItem('~L~aden', '', kbNoKey, cmLaden, hcLaden, NewItem('~T~-Rechner', '', kbNoKey, cmRechner, hcRechner, NewItem('~I~nfo', '', kbNoKey, cmInfo, hcInfo, nil))))))); end; { InitMenuBar } {-------------------------------------------------------------------------} { Statuszeile } procedure TDGL.InitStatusLine; var R : TRect; begin GetExtent(R); R.A.Y := R.B.Y - 1; StatusLine := New(PStatusLine, Init(R, NewStatusDef(0, $FFFF, NewStatusKey('~Alt-X~ Exit', kbAltX, cmQuit, NewStatusKey('~F10~ Menu', kbF10, cmMenu, NewStatusKey('~Esc~ Fenster schlieáen', kbEsc, cmClose, nil))), nil))); end; { InitStatusLine } {-------------------------------------------------------------------------} var DG : TDGL; begin { DGL } with DG do begin Init; Run; Done; end; end. { DGL } {-------------------------------------------------------------------------}
{-------------------------------------------------------------------------} { Deklarierung globaler Typen, Konstanten, Variablen, Funktionen und Prozeduren } unit DGLGlob; {$D-} {-------------------------------------------------------------------------} interface type RParameter = record DGLEingabe : string; Eingaben : array [0..3] of string [12]; end; DarstellWerte = record x, y : word; end; const cmInfo = 1002; cmRechner = 1006; cmEingabe = 1007; cmLaden = 1008; hcRechner = 4; hcInfo = 8; hcEingabe = 21; hcLaden = 22; dw_max = 5000; var Parameter : RParameter; DiffGl : string; x_min, x_max, y_anfang, e : real; nd : word; dw : array [0..dw_max] of DarstellWerte; Skala : array [0..11] of word; n_xBeschriftung, n_yBeschriftung : byte; x_Beschriftung, y_Beschriftung : array [0..9] of string; FormelCode : array [0..1000] of word; Fehler, FehlerCode : integer; Ok : boolean; function Exists(Fn : string) : boolean; procedure ValueR(Param : string; var a : real); procedure ValueI(Param : string; var i : integer); {-------------------------------------------------------------------------} implementation {--------------------------------------------------------------------------} { Prfung ob eine Datei vorhanden ist } function Exists(Fn : string) : boolean; var Datei : file; begin Assign(Datei, Fn); {$I-} Reset(Datei); {$I+} if IOResult = 0 then begin Exists := true; Close(Datei); end else Exists := false; end; { Exists } {--------------------------------------------------------------------------} { Konvertierung eines String in einen Real-Wert } procedure ValueR(Param : string; var a : real); begin Val(Param, a, Fehler); Ok := Ok and (Fehler = 0) end; { ValueR } {-------------------------------------------------------------------------} { Konvertierung eines String in einen Integer-Wert } procedure ValueI(Param : string; var i : integer); begin Val(Param, i, Fehler); Ok := OK and (Fehler = 0) end; {-------------------------------------------------------------------------} end. { DGLGlob } {--------------------------------------------------------------------------}
{-------------------------------------------------------------------------} { Eingabe-Dialog und Prfung der Eingaben } unit Input; {-------------------------------------------------------------------------} interface uses Anzeige, Compil, DGLGlob, LoadSave, Rechnung, { Turbo Pascal Standard Units } App, Dialogs, MsgBox, Objects, Views; procedure Eingabe; {-------------------------------------------------------------------------} implementation {-------------------------------------------------------------------------} { Eingabe-Dialog und Prfung der Eingaben } procedure Eingabe; var R : TRect; D, DD : PDialog; Bruce : PView; Command : word; Strng : string; AnzBytes : integer; begin { Laden der Parameter fr das Eingabefenster } ParFileRead; repeat { Parameter der letzten Rechnung } Parameter.DGLEingabe := DiffGl; Str(x_min: 8: 4, Parameter.Eingaben[0]); Str(x_max: 8: 4, Parameter.Eingaben[1]); Str(y_anfang: 8: 4, Parameter.Eingaben[2]); Str(e: 11: 10, Parameter.Eingaben[3]); { Eingabefenster } R.Assign(3, 4, 77, 18); DD := New(PDialog,Init(R,'Eingabe')); DD^.HelpCtx := hcEingabe; with DD^ do begin { Feld fr Differential-Gleichung } R.Assign(11, 3, 71, 4); Bruce := New(PInputLine, Init(R, 255)); Insert(Bruce); Strng := 'dy/dx ='; R.Assign(2, 3, 3+Length(Strng), 4); Insert(New(PLabel, Init(R, Strng, Bruce))); Strng := 'Differential-Gleichung:'; R.Assign(26, 2, 27+Length(Strng), 3); Insert(New(PStaticText, Init(R, Strng))); { Felder fr x-Wertebereich } R.Assign(32, 5, 46, 6); Bruce := New(PInputLine, Init(R, 12)); Insert(Bruce); Strng := 'x_min ='; R.Assign(20, 5, 21+Length(Strng), 6); Insert(New(PLabel, Init(R, Strng, Bruce))); R.Assign(57, 5, 71, 6); Bruce := New(PInputLine, Init(R, 12)); Insert(Bruce); Strng := 'x_max ='; R.Assign(48, 5, 49+Length(Strng), 6); Insert(New(PLabel, Init(R, Strng, Bruce))); Strng := 'x-Wertebereich:'; R.Assign(3, 5, 3+Length(Strng), 6); Insert(New(PStaticText, Init(R, Strng))); { Feld fr y-Anfangswert } R.Assign(32, 7, 46, 8); Bruce := New(PInputLine, Init(R, 12)); Insert(Bruce); Strng := 'y(x_min) ='; R.Assign(20, 7, 21+Length(Strng), 8); Insert(New(PLabel, Init(R, Strng, Bruce))); Strng := 'y-Anfangswert:'; R.Assign(3, 7, 4+Length(Strng), 8); Insert(New(PStaticText, Init(R, Strng))); { Feld fr Genauigkeit } R.Assign(32, 9, 46, 10); Bruce := New(PInputLine, Init(R, 12)); Insert(Bruce); Strng := 'e ='; R.Assign(20, 9, 21+Length(Strng), 10); Insert(New(PLabel, Init(R, Strng, Bruce))); Strng := 'Genauigkeit:'; R.Assign(3, 9, 4+Length(Strng), 10); Insert(New(PStaticText, Init(R, Strng))); { Buttons } R.Assign(21, 11, 31, 13); Insert(New(PButton, Init(R, '~B~ild', cmOk, bfDefault))); R.Assign(43, 11, 53, 13); Insert(New(PButton, Init(R, '~E~nde', cmCancel, bfNormal))); { Parameter einfgen } SetData(Parameter); Command := DeskTop^.ExecView(DD); if Command <> cmCancel then begin { Parameter einlesen } GetData(Parameter); Ok := true; DiffGl := Parameter.DGLEingabe; ValueR(Parameter.Eingaben[0], x_min); ValueR(Parameter.Eingaben[1], x_max); ValueR(Parameter.Eingaben[2], y_anfang); ValueR(Parameter.Eingaben[3], e); Ok := Ok and (x_min < x_max); end else Ok := false; if (Command = cmOk) and Ok then begin { Formel-Code erzeugen } Compile(DiffGl, FormelCode, SizeOf(FormelCode), true, Fehler, AnzBytes); if Fehler = 0 then begin { Berechnung der N„hrung und der Darstellungs-Daten } Berechnung; if FehlerCode = 0 then begin { Grafik-Ausgabe } Grafik; { Option zum Speichern der Darstellungs-Daten } R.Assign(0, 0, 45, 9); D := New(PDialog, Init(R,'Speichern ?')); with D^ do begin Options := Options or ofCentered; R.Grow(-1, -1); Dec(R.B.Y, 3); Insert(New(PStaticText, Init(R, #13+^C'Daten speichern ?'))); R.Assign(9, 6, 19, 8); Insert(New(PButton, Init(R, '~J~a', cmYes, bfDefault))); R.Assign(25, 6, 35, 8); Insert(New(PButton, Init(R, '~N~ein', cmNo, bfNormal))); end; Command := Desktop^.ExecView(D); if (Command = cmYes) then Speichern; Dispose(D, Done); end; end; end; if (Command = cmOk) and not Ok then MessageBox(#3+'Eingabefehler:'+#13+#3+'alle Werte Zahlen ?'+ #13+#3+'x_min < x_max ?', nil, mfError or mfOkButton); end; Dispose(DD, Done) until (Command = cmCancel); { Speichern der Parameter aus dem Eingabefenster } ParFileWrite; end; { Eingabe } {-------------------------------------------------------------------------} end. { Input } {-------------------------------------------------------------------------}
{-------------------------------------------------------------------------} { Berechnung der N„hrung und der Darstellungs-Daten } unit Rechnung; {-------------------------------------------------------------------------} interface uses Compil, DGLGlob, Error, { Turbo Pascal Standard Units } MsgBox, Objects; procedure DarstellBer; procedure SkalaBer; procedure Naehrung; procedure Berechnung; {-------------------------------------------------------------------------} implementation var x_next, x_last, x_skal, x_minskal, x_maxskal, x_faktor, y_next, y_last, y_skal, y_minskal, y_maxskal, y_faktor, y_min, y_max : real; {-------------------------------------------------------------------------} { Berechnung Darstellungs-Daten fr die Funktion mit erneuter Berechnung der N„hrung } procedure DarstellBer; var i, x_tmp, y_tmp : integer; h, s, y4, y5, k1, k2, k3, k4, k5, k6 : real; begin i := 1; dw[0].x := round((x_min-x_minskal)*x_faktor)+19; dw[0].y := -(round((y_anfang-y_minskal)*y_faktor)-419)+19; x_last := x_min; y_last := y_anfang; h := (x_max-x_min)/100; repeat repeat { n„chster x-Wert } x_next := x_last + h; { K-Werte } k1 := Rechne(FormelCode, x_last, y_last); k2 := Rechne(FormelCode, x_last+h/2, y_last+h*k1/2); k3 := Rechne(FormelCode, x_last+h/2, y_last+h*(k1+k2)/4); k4 := Rechne(FormelCode, x_last+h, y_last+h*(-k2+2*k3)); k5 := Rechne(FormelCode, x_last+2*h/3, y_last+h*(7*k1+10*k2+k4)/27); k6 := Rechne(FormelCode, x_last+h/5, y_last+h*(28*k1-125*k2+546*k3+54*k4-378*k5)/625); { N„hrung 4. Ordnung } y4 := y_last+h*(k1+4*k3+k4)/6; { N„hrung 5. Ordnung } y5 := y_last+h*(14*k1+35*k4+162*k5+125*k6)/336; { s-Parameter } if y4 = y5 then s := 1 else s := sqrt(sqrt(h*e/abs(y4-y5))); { Schrittweite h verkleinern } if s < 1 then if s > 1/2 then h := s*h else h := h/2; { Schrittweite h zu klein, endlose Rekursion vermeiden } if h < (x_max-x_min)/1000000 then h := (x_max-x_min)/1000000; until (s >= 1) or (h <= (x_max-x_min)/999999); { berechneten y-Wert bernehmen } y_next := y5; { Schrittweite h vergr”áern } if s >= 1 then if s < 2 then h := s*h else h := 2*h; x_last := x_next; y_last := y_next; { Darstellungs-Daten bestimmen } x_tmp := round((x_next-x_minskal)*x_faktor)+19; y_tmp := -(round((y_next-y_minskal)*y_faktor)-419)+19; if (x_tmp <> dw[i-1].x) or (y_tmp <> dw[i-1].y) then begin dw[i].x := x_tmp; dw[i].y := y_tmp; inc(i); end; until (x_last >= x_max) or (i = dw_max); nd := i-1; end; { DarstellBer } {-------------------------------------------------------------------------} { Berechnung der Darstellungs-Daten fr das Koordinaten-System } procedure SkalaBer; {-------------------------------------------------------------------------} { Berechnung von Zehnerpotenzen aus dem Exponenten } function Zehnerpotenz(Exponent : integer) : real; var i : integer; Ergebnis : real; Strng : string; begin Strng := '1'; if Exponent > 0 then for i := 1 to Exponent do Strng := Strng+'0'; if Exponent < -1 then for i := -2 downto Exponent do Strng := '0'+Strng; if Exponent < 0 then Strng := '0.'+Strng; ValueR(Strng, Ergebnis); Zehnerpotenz := Ergebnis; end; { Zehnerpotenz } {-------------------------------------------------------------------------} var i, sig, exp : integer; skalmitte, tmpR : real; tmpS : string [24]; abschneiden : boolean; begin { SkalBer } { x-Skalenweite } tmpR := (x_max-x_min)/8; str(tmpR, tmpS); ValueI(copy(tmpS, 2, 1), sig); ValueI(copy(tmpS, 19, 5), exp); case sig of 0 : x_skal := 1; 1 : x_skal := 2; 2..4 : x_skal := 5; 5..9 : x_skal := 10; end; x_skal := x_skal*(Zehnerpotenz(exp)); { Mitte der x-Skala } skalmitte := (x_min+x_max)/2; if skalmitte >= 0 then begin tmpR := -x_skal; repeat tmpR := tmpR+x_skal; until skalmitte-tmpR <= 0; skalmitte := tmpR; end else begin tmpR := x_skal; repeat tmpR := tmpR-x_skal; until skalmitte-tmpR >= 0; skalmitte := tmpR; end; { x-Minimal- und -Maximal-Skalenwert } x_minskal := skalmitte; repeat x_minskal := x_minskal-x_skal; until x_minskal < x_min+0.1*x_skal; x_maxskal := skalmitte; repeat x_maxskal := x_maxskal+x_skal; until x_maxskal > x_max-0.1*x_skal; { x-Skalenbeschriftung } i := 0; tmpR := x_minskal; repeat tmpR := tmpR+x_skal; if abs(tmpR) > 0.5*x_skal then begin Str(tmpR, tmpS); if exp < 0 then begin if copy(tmpS, 4-exp, 1) = '9' then begin tmpR := tmpR+0.1*Zehnerpotenz(exp); Str(tmpR, tmpS); end; x_Beschriftung[i] := copy(tmpS, 1, 3-exp)+copy(tmpS, 18, 2)+copy(tmpS, 22, 2); end else x_Beschriftung[i] := copy(tmpS, 1, 4)+copy(tmpS, 18, 2)+copy(tmpS, 22, 2); end else begin tmpR := 0; x_Beschriftung[i] := ''; end; inc(i); until tmpR >= x_maxskal-0.5*x_skal; n_xBeschriftung := i-1; { nichtsignifikante x-Stellen abschneiden } repeat abschneiden := false; if length(x_Beschriftung[i]) > 8 then begin i := -1; repeat abschneiden := false; inc(i); if copy(x_Beschriftung[i], length(x_Beschriftung[i])-4, 1) = '0' then abschneiden := true; until (abschneiden = false) or (i = n_xBeschriftung); abschneiden := false; if i = n_xBeschriftung then begin abschneiden := true; for i := 0 to n_xBeschriftung do x_Beschriftung[i] := copy(x_Beschriftung[i], 1, length(x_Beschriftung[i])-5)+ copy(x_Beschriftung[i], length(x_Beschriftung[i])-3, 4); end; end; until (abschneiden = false); { y-Skalenweite } tmpR := (y_max-y_min)/8; str(tmpR, tmpS); ValueI(copy(tmpS, 2, 1), sig); ValueI(copy(tmpS, 19, 5), exp); case sig of 0 : y_skal := 1; 1 : y_skal := 2; 2..4 : y_skal := 5; 5..9 : y_skal := 10; end; y_skal := y_skal*(Zehnerpotenz(exp)); { Mitte der y-Skala } skalmitte := (y_min+y_max)/2; if skalmitte >= 0 then begin tmpR := -y_skal; repeat tmpR := tmpR+y_skal; until skalmitte-tmpR <= 0; skalmitte := tmpR; end else begin tmpR := y_skal; repeat tmpR := tmpR-y_skal; until skalmitte-tmpR >= 0; skalmitte := tmpR; end; { y-Minimal- und -Maximal-Skalenwert } y_minskal := skalmitte; repeat y_minskal := y_minskal-y_skal; until y_minskal < y_min+0.1*y_skal; y_maxskal := skalmitte; repeat y_maxskal := y_maxskal+y_skal; until y_maxskal > y_max-0.1*y_skal; { y-Skalenbeschriftung } i := 0; tmpR := y_minskal; repeat tmpR := tmpR+y_skal; if abs(tmpR) > 0.5*y_skal then begin Str(tmpR, tmpS); if exp < 0 then begin if copy(tmpS, 4-exp, 1) = '9' then begin tmpR := tmpR+0.1*Zehnerpotenz(exp); Str(tmpR, tmpS); end; y_Beschriftung[i] := copy(tmpS, 1, 3-exp)+copy(tmpS, 18, 2)+copy(tmpS, 22, 2); end else y_Beschriftung[i] := copy(tmpS, 1, 4)+copy(tmpS, 18, 2)+copy(tmpS, 22, 2); end else begin tmpR := 0; y_Beschriftung[i] := ''; end; inc(i); until tmpR >= y_maxskal-0.5*y_skal; n_yBeschriftung := i-1; { nichtsignifikante y-Stellen abschneiden } repeat abschneiden := false; if length(y_Beschriftung[i]) > 8 then begin i := -1; repeat abschneiden := false; inc(i); if copy(y_Beschriftung[i], length(y_Beschriftung[i])-4, 1) = '0' then abschneiden := true; until (abschneiden = false) or (i = n_yBeschriftung); abschneiden := false; if i = n_yBeschriftung then begin abschneiden := true; for i := 0 to n_yBeschriftung do y_Beschriftung[i] := copy(y_Beschriftung[i], 1, length(y_Beschriftung[i])-5)+ copy(y_Beschriftung[i], length(y_Beschriftung[i])-3, 4); end; end; until (abschneiden = false); { Umrechnungsfaktoren fr Bildschirmdarstellung } x_faktor := 600/(x_maxskal-x_minskal); y_faktor := 420/(y_maxskal-y_minskal); { x-Achse } if x_minskal < 0.5*x_skal then Skala[0] := 19 else Skala[0] := 39; if y_minskal > -0.5*y_skal then Skala[1] := 439 else if y_maxskal < 0.5*y_skal then Skala[1] := 19 else Skala[1] := -(round((-y_minskal)*y_faktor)-419)+19; if x_maxskal > -0.5*x_skal then Skala[2] := 619 else Skala[2] := 599; { y-Achse } if x_minskal > -0.5*x_skal then Skala[3] := 19 else if x_maxskal < 0.5*x_skal then Skala[3] := 619 else Skala[3] := round((-x_minskal)*x_faktor)+19; if y_maxskal > -0.5*y_skal then Skala[4] := 19 else Skala[4] := 39; if y_minskal < 0.5*y_skal then Skala[5] := 439 else Skala[5] := 419; { Skalierungsfaktoren } Skala[6] := round(x_skal*x_faktor); Skala[7] := round(y_skal*y_faktor); end; { SlalaBer } {-------------------------------------------------------------------------} { Berechnung der N„hrung } procedure Naehrung; var h, s, y4, y5, k1, k2, k3, k4, k5, k6 : real; begin y_min := y_anfang; y_max := y_anfang; x_last := x_min; y_last := y_anfang; h := (x_max-x_min)/100; repeat repeat { n„chster x-Wert } x_next := x_last + h; { K-Werte } k1 := Rechne(FormelCode, x_last, y_last); k2 := Rechne(FormelCode, x_last+h/2, y_last+h*k1/2); k3 := Rechne(FormelCode, x_last+h/2, y_last+h*(k1+k2)/4); k4 := Rechne(FormelCode, x_last+h, y_last+h*(-k2+2*k3)); k5 := Rechne(FormelCode, x_last+2*h/3, y_last+h*(7*k1+10*k2+k4)/27); k6 := Rechne(FormelCode, x_last+h/5, y_last+h*(28*k1-125*k2+546*k3+54*k4-378*k5)/625); { N„hrung 4. Ordnung } y4 := y_last+h*(k1+4*k3+k4)/6; { N„hrung 5. Ordnung } y5 := y_last+h*(14*k1+35*k4+162*k5+125*k6)/336; { s-Parameter } if y4 = y5 then s := 1 else s := sqrt(sqrt(h*e/abs(y4-y5))); { Schrittweite h verkleinern } if s < 1 then if s > 1/2 then h := s*h else h := h/2; { Schrittweite h zu klein, endlose Rekursion vermeiden } if h < (x_max-x_min)/1000000 then h := (x_max-x_min)/1000000; until (s >= 1) or (h <= (x_max-x_min)/999999); { berechneten y-Wert bernehmen } y_next := y5; { Schrittweite h vergr”áern } if s >= 1 then if s < 2 then h := s*h else h := 2*h; { y-Grenzen } if y_next < y_min then y_min := y_next; if y_next > y_max then y_max := y_next; x_last := x_next; y_last := y_next; until x_last >= x_max; end; { Naehrung } {-------------------------------------------------------------------------} { Prfung ob Rechnung durchgefhrt werden kann und Start der Rechnung } procedure Berechnung; var Strng, Strng1, Strng2 : string; begin FehlerCode := SetExit(CpuPointer); case FehlerCode of 0 : begin Naehrung; SkalaBer; DarstellBer; end; 200 : Strng := 'Division durch 0'; 205 : Strng := 'Flieákommaberlauf'; 206 : Strng := 'Flieákommazahl zu klein'; 207 : Strng := 'Unzul„ssige Werte' else Strng := 'Rechenfehler unbekannter Art' end; if FehlerCode <> 0 then begin Str(x_last: 8: 3, Strng1); Strng1 := 'x = ' + Strng1; Str(y_last: 8: 3, Strng2); Strng2 := 'y = ' + Strng2; MessageBox(#3+Strng+#13+#3+Strng1+#13+#3+Strng2, nil, mfError or mfOKButton); end; end; { Berechnung } {-------------------------------------------------------------------------} end. { Rechnung } {-------------------------------------------------------------------------}
{-------------------------------------------------------------------------} { Erzeugung des Formel-Codes aus der Differential-Gleichung und Berechnung der K-Werte mit dem Formel-Code } unit Compil; {-------------------------------------------------------------------------} interface uses DGLGlob, Error, { Turbo Pascal Standard Units } MsgBox, Objects, Views; function Rechne(var Code; x, y : real): real; procedure Compile(var Ausdruck; var Code; Size : integer; Meldung : boolean; var ErrPos, Pc : integer); {-------------------------------------------------------------------------} implementation var CpuSave : ExitBuf; {-------------------------------------------------------------------------} { Berechnung der K-Werte mit dem Formel-Code } function Rechne(var Code; x, y : real) : real; const MaxStack = 50; var Pc, Sp : integer; Oc : byte; Stack : array [0..MaxStack] of real; OpCode : array [0..MaxInt] of byte absolute Code; begin Pc := 0; Sp := 0; repeat Oc := OpCode[Pc]; Inc(Pc); case Oc of 0 : begin Inc(Sp); Stack[Sp] := x; end; 1 : begin Inc(Sp); Stack[Sp] := y; end; 2 : begin Inc(Sp); Move(OpCode[Pc], Stack[Sp], SizeOf(real)); Inc(Pc, SizeOf(real)); end; 3 : begin Dec(Sp); Stack[Sp] := Stack[Sp]+Stack[Succ(Sp)]; end; 4 : begin Dec(Sp); Stack[Sp] := Stack[Sp]-Stack[Succ(Sp)]; end; 5 : begin Dec(Sp); Stack[Sp] := Stack[Sp]*Stack[Succ(Sp)]; end; 6 : begin Dec(Sp); Stack[Sp] := Stack[Sp]/Stack[Succ(Sp)]; end; 7 : Stack[Sp] := Sin(Stack[Sp]); 8 : Stack[Sp] := Cos(Stack[Sp]); 9 : Stack[Sp] := Sin(Stack[Sp])/Cos(Stack[Sp]); 10 : Stack[Sp] := ArcTan(Stack[Sp]); 11 : Stack[Sp] := Exp(Stack[Sp]); 12 : Stack[Sp] := Ln(Stack[Sp]); 13 : Stack[Sp] := Ln(Stack[Sp])/Ln(10.0); 14 : Stack[Sp] := Sqr(Stack[Sp]); 15 : Stack[Sp] := Sqrt(Stack[Sp]); 16 : Stack[Sp] := Frac(Stack[Sp]); 17 : Stack[Sp] := Int(Stack[Sp]); 18 : Stack[Sp] := Abs(Stack[Sp]); 19 : Stack[Sp] := -Stack[Sp]; end; until Oc >= 20; Rechne := Stack[1]; end; { Rechne } {-------------------------------------------------------------------------} { Erzeugung des Formel-Codes aus der Differential-Gleichung } procedure Compile(var Ausdruck; var Code; Size : integer; Meldung : boolean; var ErrPos, Pc : integer); type RunTime = (LoadVarX, LoadVarY, Push, Add, Sub, Mult, Divi, Sin, Cos, Tan, ArcTan, Exp, Ln, Log, Sqr, Sqrt, Frac, Int, Abs, Neg, Stop); Str1 = string [1]; const FNam : array [Sin..Abs] of string [6] = ('SIN', 'COS', 'TAN', 'ARCTAN', 'EXP', 'LN', 'LOG', 'SQR', 'SQRT', 'FRAC', 'INT', 'ABS'); var Formel : string [255] absolute Ausdruck; OpCode : array [0..MaxInt] of Runtime absolute Code; Chp, Tiefe : integer; K, Dummy : word; Ch : char; {-------------------------------------------------------------------------} procedure Fehler(Nr : integer); var i, j : integer; R : TRect; Strng, Strng1 : string; begin if Meldung then begin case Nr of 0 : Strng1 := 'Speicherplatz im Codefeld reicht nicht'; 1 : Strng1 := 'Operator erwartet'; 2 : Strng1 := '"(" erwartet'; 3 : Strng1 := 'Unbekannte Funktion'; 4 : Strng1 := '")" erwartet'; 5 : Strng1 := 'Konstante, Variable oder Funktion erwartet'; 6 : Strng1 := 'Fehler in Konstante'; 7 : Strng1 := 'Klammer-Fehler' end; Strng := ''; for i := 1 to Chp-1 do Strng := Strng + ' '; Strng := Strng + '^'; j := Length(Strng); for i := j+1 TO Length(Formel) do Strng := Strng + ' ' end; if ErrPos = 0 then ErrPos := Chp; R.Assign(13, 6, 67, 17); MessageBoxRect(R, #3+Formel+#13+#3+Strng+#13+#13+#3+Strng1, nil, mfError or mfOKButton); LongExit(CpuSave, Dummy); end; { Fehler } {-------------------------------------------------------------------------} procedure GetChar; begin repeat Inc(Chp); if Chp > Length(Formel) then Ch := #0 else Ch := Upcase(Formel[Chp]); until Ch <> ' ' end; { GetChar } {-------------------------------------------------------------------------} procedure PutCode(B : Runtime); begin if Pc >= Size then Fehler(0) else OpCode[Pc] := B; Inc(Pc) end; { PutCode } {-------------------------------------------------------------------------} procedure PutReal(R : real); begin if Pc + SizeOf(real) >= Size then Fehler(0) else Move(R, Opcode[Pc], SizeOf(real)); Inc(Pc,SizeOf(real)) end; { PutReal } {-------------------------------------------------------------------------} procedure AddSub; Forward; {-------------------------------------------------------------------------} procedure Konstante (var Vorz : Str1); var Fp : real; Err1, Err2 : integer; begin Val(Copy(Formel, Chp, 255)+'?', Fp, Err1); Val(Vorz+Copy(Formel, Chp, pred(err1)), fp, Err2); if Err2 <> 0 then Fehler(6); PutCode(Push); PutReal(Fp); Chp := Chp + Err1 - 2; GetChar; if not (Ch in ['-','+','/','*',')',#0]) then Fehler(1) end; { Konstante } {-------------------------------------------------------------------------} procedure Term; var Name : string [6]; i, S : Runtime; Vorz : Str1; begin GetChar; if Ch in [#0,')'] then begin Fehler(5); Exit end; if Ch = '-' then begin Vorz := '-'; GetChar end else Vorz := ''; if Ch = '(' then begin Inc(Tiefe); AddSub; Dec(Tiefe); if Ch <> ')' then begin Fehler(4); Exit end; GetChar end else if Ch in ['0'..'9'] then Konstante(Vorz) else begin Name := ''; while Ch in ['A'..'Z'] do begin Name := Name + Ch; GetChar end; if Name = 'X' then PutCode(LoadVarX); if Name = 'Y' then PutCode(LoadVarY); if (Name <> 'X') and (Name <> 'Y') then begin S := LoadVarX; for i := Sin to Abs do if Name = FNam[i] then S := I; S := LoadVarY; for i := Sin to Abs do if Name = FNam[i] then S := I; if (S <> LoadVarX) or (S <> LoadVarY) then begin if Ch <> '(' then Fehler(2); Dec(Chp); Term; PutCode(S); end else Fehler(3); end; if Vorz = '-' then PutCode(Neg) end; end; { Term } {-------------------------------------------------------------------------} procedure MultDiv; begin repeat case Ch of '*' : begin Term; PutCode(Mult) end; '/' : begin Term; PutCode(Divi) end; end; until not (Ch in ['*', '/']); end; { MultDiv } {-------------------------------------------------------------------------} procedure AddSub; begin Term; if ErrPos = 0 then repeat case Ch of '-' : begin Term; MultDiv; PutCode(Sub) end; '+' : begin Term; MultDiv; PutCode(Add) end; '(' : Fehler(1); ')' : begin if Tiefe = 0 then Fehler(7); Exit; end; '*', '/' : MultDiv; #0 : else Fehler(1); end; until (Ch = #0) or (ErrPos <> 0); end; { AddSub } {-------------------------------------------------------------------------} begin { Compile } K := SetExit(CpuSave); if K = 0 then begin Chp := 0; Pc := 0; ErrPos := 0; Tiefe := 0; AddSub; PutCode(Stop) end; end; { Compile } {-------------------------------------------------------------------------} end. { Compil } {-------------------------------------------------------------------------}
{-------------------------------------------------------------------------} { Initialisierung des Grafik-Bildschirmes und Ausgabe der Grafik } unit Anzeige; {-------------------------------------------------------------------------} interface uses DGLGlob, { Turbo Pascal Standard Units } Crt, Dos, Graph, GraphApp, MsgBox, Objects; procedure Grafik; {-------------------------------------------------------------------------} implementation {-------------------------------------------------------------------------} { Initialisierung des Grafik-Bildschirmes } procedure Grafik; {-------------------------------------------------------------------------} { Ausgabe der Grafik } procedure GrafikAnzeige; var i, j : integer; Strng : string; begin { feste Elemente einfgen } Rectangle(0, 0, GetMaxX, GetMaxY); Line(0, 459, GetMaxX, 459); Line(485, 459, 485, GetMaxY); Strng := 'Weiter mit'; OutTextXY(500, 466, Strng); { Differential-Gleichung ausgeben } Strng := 'dy/dx = '+DiffGl; OutTextXY(15, 466, Strng); { Koordinatenkreuz zeichnen } Line(Skala[0], Skala[1], Skala[2], Skala[1]); OutTextXY(Skala[2]-20, Skala[1]-10, 'x'); Line(Skala[3], Skala[4], Skala[3], Skala[5]); OutTextXY(Skala[3]-10, Skala[4]+10, 'y'); { Skalenstriche zeichnen und Skalenbeschriftung } i := 19+Skala[6]; j := 0; repeat if abs(Skala[3]-i) < 10 then i := Skala[3]; Line(i, Skala[1]-3, i, Skala[1]+3); OutTextXY(i-30, Skala[1]+8, x_Beschriftung[j]); i := i+Skala[6]; inc(j); until i > 604; i := 439-Skala[7]; j := 0; repeat if abs(Skala[1]-i) < 10 then i := Skala[1]; Line(Skala[3]-3, i, Skala[3]+3, i); if Skala[3] < 559 then OutTextXY(Skala[3]+8, i-3, y_Beschriftung[j]) else OutTextXY(Skala[3]-10*length(y_Beschriftung[j])+10, i-3, y_Beschriftung[j]); i := i-Skala[7]; inc(j); until i < 34; { Hilfspunkte zeichnen } i := 19; repeat if abs(Skala[3]-i) < 10 then i := Skala[3]; j := 439; repeat if abs(Skala[1]-j) < 10 then j := Skala[1]; PutPixel(i, j, white); PutPixel(619, j, white); j := j-Skala[7]; until j < 34; PutPixel(i, 19, white); i := i+Skala[6]; until i > 604; PutPixel(619, 19, white); { Funktion zeichnen } for i := 0 to nd do PutPixel(dw[i].x, dw[i].y, yellow); end; { GrafikAnzeige } {-------------------------------------------------------------------------} var BGIPath : PString; GraphOk : boolean; Taste : char; begin { Grafik } BGIPath := NewStr(FExpand('.')); GraphOk := GraphAppInit(0, 0, BGIPath, true); if not GraphOk then MessageBox(#3+'Kann Grafiktreiber nicht finden', nil, mfOKButton or mfError); if GraphicsStart then begin GrafikAnzeige; repeat Taste := readkey until Taste in [chr(27)]; { Escape-Taste } GraphicsStop; end; end; { Grafik } {-------------------------------------------------------------------------} end. { Anzeige } {-------------------------------------------------------------------------}
{-------------------------------------------------------------------------} { Laden und Speichern von Dateien } unit LoadSave; {-------------------------------------------------------------------------} interface uses Anzeige, DGLGlob, { Turbo Pascal Standard Units } App, Dialogs, MsgBox, Objects, StdDlg, Views; procedure ParFileRead; procedure ParFileWrite; procedure Laden; procedure Speichern; {-------------------------------------------------------------------------} implementation const ParFileName : string = 'DGL.PAR'; Extens : string = '*.DGL'; var ParamFile, DatFile : text; FileName : string; {-------------------------------------------------------------------------} { Laden der Parameter fr das Eingabefenster } procedure ParFileRead; begin if Exists(ParFileName) then begin Assign(ParamFile, ParFileName); Reset(ParamFile); ReadLn(ParamFile, DiffGl); ReadLn(ParamFile, x_min); ReadLn(ParamFile, x_max); ReadLn(ParamFile, y_anfang); ReadLn(ParamFile, e); Close(ParamFile) end else begin DiffGl := 'cos(x)*y'; x_min := -8; x_max := 0; y_anfang := exp(sin(-8)); e := 0.000000001; end; end; { ParFileRead } {-------------------------------------------------------------------------} { Speichern der Parameter aus dem Eingabefenster } procedure ParFileWrite; begin Assign(ParamFile, ParFileName); ReWrite(ParamFile); WriteLn(ParamFile, DiffGl); WriteLn(ParamFile, x_min); WriteLn(ParamFile, x_max); WriteLn(ParamFile, y_anfang); WriteLn(ParamFile, e); Close(ParamFile); end; { ParFileWrite } {-------------------------------------------------------------------------} { ™ffnen einer Darstellungs-Datei } procedure Laden; {-------------------------------------------------------------------------} { Laden der Daten einer Dartellungs_Datei } procedure DatFileRead; var i : word; begin Assign(DatFile, FileName); Reset(DatFile); ReadLn(DatFile, DiffGl); for i := 0 to 7 do ReadLn(DatFile, Skala[i]); ReadLn(Datfile, n_xBeschriftung); for i := 0 to n_xBeschriftung do ReadLn(Datfile, x_Beschriftung[i]); ReadLn(Datfile, n_yBeschriftung); for i := 0 to n_yBeschriftung do ReadLn(Datfile, y_Beschriftung[i]); ReadLn(DatFile, nd); for i := 0 to nd do begin ReadLn(DatFile, dw[i].x); ReadLn(DatFile, dw[i].y); end; Close(DatFile); end; { DatFileRead } {-------------------------------------------------------------------------} var R : TRect; D : PFileDialog; Command : word; begin { Laden } repeat D := New(PFileDialog, Init(Extens, 'Datei ”ffnen', '~N~ame', fdOpenButton, fdReplaceButton)); Command := Desktop^.ExecView(D); if (Command <> cmCancel) then begin D^.GetFileName(FileName); if Exists(FileName) then begin DatFileRead; Grafik; end else MessageBox(#3+'Datei nicht gefunden'+#13+#13, nil, mfError or mfOKButton); end; Dispose(D, Done); until (Command = cmCancel); end; { Laden } {-------------------------------------------------------------------------} { Abspeichern einer Darstellungs-Datei } procedure Speichern; {-------------------------------------------------------------------------} { Speichern der Daten einer Darstellungs-Datei } procedure DatFileWrite; var i : word; begin Assign(DatFile, FileName); ReWrite(DatFile); WriteLn(DatFile, DiffGl); for i := 0 to 7 do WriteLn(DatFile, Skala[i]); WriteLn(Datfile, n_xBeschriftung); for i := 0 to n_xBeschriftung do WriteLn(Datfile, x_Beschriftung[i]); WriteLn(Datfile, n_yBeschriftung); for i := 0 to n_yBeschriftung do WriteLn(Datfile, y_Beschriftung[i]); WriteLn(DatFile, nd); for i := 0 to nd do begin WriteLn(DatFile, dw[i].x); WriteLn(DatFile, dw[i].y); end; Close(DatFile); end; { DatFileWrite } {-------------------------------------------------------------------------} var R : TRect; D : PFileDialog; begin { Speichern } Ok := false; repeat D := New(PFileDialog, Init(Extens, 'Datei speichern', '~N~ame', fdOkButton, fdReplaceButton)); if Desktop^.ExecView(D) <> cmCancel then begin D^.GetFileName(FileName); if Exists(FileName) then begin if MessageBox(#3+'Datei existiert!'+#13+#3+'šberschreiben?', nil, mfInformation or mfOkCancel) = cmOk then begin Assign(DatFile, FileName); Erase(DatFile); DatFileWrite; Ok := true; end; end else DatFileWrite; Ok := true end else Ok:= true; Dispose(D, Done); until Ok = true; end; { Speichern } {-------------------------------------------------------------------------} end. { LoadSave } {-------------------------------------------------------------------------}
{-------------------------------------------------------------------------} { Abfangen von Fehlern in der Berechnung } unit Error; {$F+} {-------------------------------------------------------------------------} interface type ExitBuf = record Bp, Cs, Ip : word end; var CpuPointer : ExitBuf; ErrCode : word; function SetExit(var CpuSave : ExitBuf) : word; procedure LongExit(var CpuSave : ExitBuf; RetV : word); {-------------------------------------------------------------------------} implementation var Stack : record case boolean of true : (Offset, Segment : word); false : (Zeiger : ^word) end; ExitSave : pointer; {-------------------------------------------------------------------------} function SetExit(var CpuSave : ExitBuf) : word; begin with Stack do begin Zeiger := Ptr(SSeg, SPtr+2); CpuSave.bp := Zeiger^; Inc(Offset, 2); CpuSave.ip := Zeiger^; Inc(Offset, 2); CpuSave.cs := Zeiger^ end; SetExit := 0 end; { SetExit } {-------------------------------------------------------------------------} procedure LongExit(var CpuSave : ExitBuf; RetV : word); var Dummy : word; begin with Stack do begin Zeiger := Ptr(SSeg, SPtr+2); Zeiger^ := CpuSave.bp; Inc(Offset, 2); Zeiger^ := CpuSave.ip; Inc(Offset, 2); Zeiger^ := CpuSave.cs; end; Dummy := RetV end; { LongExit } {-------------------------------------------------------------------------} procedure MyExit; begin ExitProc := ExitSave; if ExitCode in [200, 205, 206, 207] then begin ErrCode := ExitCode; ExitCode := 0; ErrorAddr := nil; ExitProc := @MyExit; LongExit(CpuPointer, ErrCode) end; end; { MyExit } {-------------------------------------------------------------------------} begin ExitSave := ExitProc; ExitProc := @MyExit end. { Error } {-------------------------------------------------------------------------}
{-------------------------------------------------------------------------} { zus„tzlichen Programmteile } unit Etc; {-------------------------------------------------------------------------} interface uses DGLGlob, { Turbo Pascal Standard Units } App, Dialogs, Calc, Objects, Views; procedure Rechner; procedure Info; {-------------------------------------------------------------------------} implementation {-------------------------------------------------------------------------} { einfacher Taschenrechner aus Turbo Pascal Standard Unit } procedure Rechner; var P : PCalculator; begin P := New(PCalculator, Init); P^.HelpCtx := hcRechner; Desktop^.Insert(P); end; { Rechner } {-------------------------------------------------------------------------} { Programm-Information } procedure Info; var D : PDialog; R : TRect; begin R.Assign(0, 0, 45, 11); D := New(PDialog, Init(R,'Info')); with D^ do begin Options := Options or ofCentered; R.Grow(-1, -1); Dec(R.B.Y, 3); Insert(New(PStaticText, Init(R, #13+^C'Numerische L”sung von expliziten'#13+ ^C'Differential-Gleichungen erster Ordnung'#13+ #13+^C'1996/97'#13+^C'Udo Becker'))); R.Assign(17, 8, 27, 10); Insert(New(PButton, Init(R, '~O~K', cmOk, bfDefault))); end; Desktop^.ExecView(D); Dispose(D, Done); end; { Info } {-------------------------------------------------------------------------} end. { Etc } {-------------------------------------------------------------------------}
Auf der Programmdiskette befinden sich folgende Dateien:
Hauptverzeichnis \:
DGL.EXE | Programm DGL |
DGL.PAR | Parameter-Datei |
EGAVGA.BGI | Borland Graphic Interface |
BEISP1.DGL | Beispieldatei |
BEISP2A.DGL | Beispieldatei |
BEISP2B.DGL | Beispieldatei |
BEISP2C.DGL | Beispieldatei |
Unterverzeichnis \SOURCE:
DGL.PAS | Hauptprogramm |
DGLGLOB.PAS | Globale Deklarationen |
INPUT.PAS | Eingaberoutine |
RECHNUNG.PAS | Berechnungen |
COMPIL.PAS | Berechnungshilfen |
ANZEIGE.PAS | Grafische Ausgabe |
LOADSAVE.PAS | Laden und Speichern |
ERROR.PAS | Fehlerbehandlung |
ETC.PAS | zusätzliche Programmteile |
13. August 2000, Udo Becker