Entwickler-Ecke

Sonstiges (Delphi) - Mathematisches Problem mit Nullstellenberechnung


VirusX - Sa 08.03.03 16:24
Titel: Mathematisches Problem mit Nullstellenberechnung
Ich möchte ein einfaches Programm schreiben, oder besser gesagt, bin gerade dabei eins zu schreiben, dass mir von einer mathematischen Funktion
f(x) =a 5*x^5 + a4*x^4 + a3*x^3 + a2*x^2 + a1*x + ao
die Nullstellen berechnet.
Nur leider bekomm ich das ganze nicht zum Laufen.
Wenn jemand schon ein solches Programm hat oder mir (über ICQ) bei meinem Programm helfen kann (Sourcecode wird gesendet!), wäre ich sehr dankbar!


Popov - Sa 08.03.03 16:30

Guck dir mal Power an.


UGrohne - Sa 08.03.03 17:06

Ich hatte da mal was, das lief über Matrizen, ich suchs grad mal raus. Hoffe, ich hab die CD net weggeworfen :cry:

War damals net einfach, das Teil zu schreiben... habs aus nem Buch raus

Gruß


VirusX - Sa 08.03.03 17:33

Was ist "power"?
Also allzu kompliziert sollts auch nicht sein. Aber trotzdem danke für die Bemühung!


Popov - Sa 08.03.03 17:44

Einfach Delphihilfe aufrufen und Power eingeben und schon hat man die Antwort.

x^2

ist in Delphi

Power(x, 2)


VirusX - Sa 08.03.03 18:55

Das Problem ist nicht das x^2, das bekomm ich auch mit x*x hin, sondern dass mir von der Funktion die Nullstellen nicht ausgegeben werden, in der Endausgabe. Das bekomm ich nicht hin.


Popov - Sa 08.03.03 19:07

Also ist das kein Programmtechnisches Problem, sondern nur ein Mathematisches. Wieso stellst du dann die Frage in einem Delphiforum?


Delphianer23 - Sa 08.03.03 19:11

und die Variable a ist wohl nicht bei jeder potenz die gleiche also eher:(wenn es eineallgemeine Formel sein soll)

f(x) =a 5*x^5 + b4*x^4 + c3*x^3 + d2*x^2 + ex + f
......................................................................................
Zumindest ich kann da rein Mahtematisch nichts machen, höchstens ausprobieren, ob eine gerade Zahl passt und dann mit dem Ergebnis Polynomdivision durchführen.(Bei uns in der Schule würde ichs so machen)

Mit dem Computer gibt es doch noch andere Möglichkeiten:
..............................................................

Man könnte z.B Für Zahlen von

-3000 bis +3000 druchlaufen lassen, dafür immer den y Wert ermitteln zwischen denen Zahlen wo es dann zwischen einem - Ergebnnis und einem Plusergebnis wecheslt nochmal.

z.B

für 2344 ERgebnis = +2.325424
für 2345 ergebnis =-1.2323

Das bedeutet, dass dazwishcen eine Nullstelle sein muss. Dein ERgenis ist also zwischen 2344 und 2345. Das ist zu ungenau, also weiter ...

Nun weiter (Bereich zwischen den Zahlen aufteilen, um genaueren WErt zu erhalten):

Quelltext
1:
2:
3:
4:
5:
6:
for zähler:= 0 to 6000 do 
 beign
{2344+ ((2345-2344)/6000)* Zähler }
Dieses Ergebnis wieder in die Funktion einsetzen und 
Werte ermitteln
 end;

dafür kommen nun wieder 6000 Ergebnisst raus, dort wo es dann zwischen - und + Wechselt, die FUnktion zwischen den beiden neuen Zahlen wieder durchführen. Dieses Prozess beliebig wiederholen bis die gewünschte Genauigkeit erreicht ist.

Nachtiel: Bei sehr kleinen SChwankungen um die x Achse könnten beim ersten Schritt einige Ergebnisse verloren gehen. Dann muss man es halt genauer machen. Dies bedeutet kleinere Zahlenabstände wählen.

Auf diesem Weg müsstest du es doch hinkriegen oder?

Moderiert von user profile iconTino: Absätze entfernt & Code-Tags hinzugefügt.


VirusX - Sa 08.03.03 20:04

Popov hat folgendes geschrieben:
Also ist das kein Programmtechnisches Problem, sondern nur ein Mathematisches. Wieso stellst du dann die Frage in einem Delphiforum?

Natürlich ist es ein Problem mit Delphi. Soweit kenn ich mich dann doch aus...
Danke für deine Hilfe, blutiges Elend. Hier geb ich euch mal den Quelltext. Da ist noch irgendwo ein Fehler drin, den ich nicht rausbekomm...

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
procedure TForm1.Button1Click(Sender: TObject);
var a1,a2,a3,a4,a5,ao,fa,fb,fm,m:single;
    a,b,e:single;
label
    Wiederholung, Ende, Ausgabe;

begin
  ao:=StrToFloat(Edit1.Text);
  a1:=StrToFloat(Edit2.Text);
  a2:=StrToFloat(Edit3.Text);
  a3:=StrToFloat(Edit4.Text);
  a4:=StrToFloat(Edit5.Text);
  a5:=StrToFloat(Edit6.Text);
  a:=spinedit1.value ;
  b:=spinedit2.value;
  e:=StrToFloat(Edit10.Text);
  fa:=(a5*a*a*a*a*a)+(a4*a*a*a*a)+(a3*a*a*a)+(a2*a*a)+(a1*a)+ao;
  fb:=(a5*b*b*b*b*b)+(a4*b*b*b*b)+(a3*b*b*b)+(a2*b*b)+(a1*b)+ao;
  if fa*fb>0 then
  begin
  label10.Caption:='Falsches Intervall'
  end else
  Wiederholung:
  m:=(a+b)/2;
  fm:=a5*m*m*m*m*m+a4*m*m*m*m+a3*m*m*m+a2*m*m+a1*m+ao;
  if fa*fm<=0  then
  b:=m ;
  goto Ende;

  a:=m;
  Ende:
  fm:=a5*m*m*m*m*m+a4*m*m*m*m+a3*m*m*m+a2*m*m+a1*m+ao;
  if fm *fm<=e*e then
  goto Ausgabe
  else
  goto Wiederholung;
  Ausgabe:
  Edit6.Text:=FloatToStr(m);
  end;

procedure TForm1.SpinEdit1Change(Sender: TObject);
var a,fa,a1,a2,a3,a4,a5,ao:single;
begin
 a:=spinedit1.value ;
 ao:=StrToFloat(Edit1.Text);
  a1:=StrToFloat(Edit2.Text);
  a2:=StrToFloat(Edit3.Text);
  a3:=StrToFloat(Edit4.Text);
  a4:=StrToFloat(Edit5.Text);
  a5:=StrToFloat(Edit6.Text);
 fa:=(a5*a*a*a*a*a)+(a4*a*a*a*a)+(a3*a*a*a)+(a2*a*a)+(a1*a)+ao;
  Edit8.Text:=FloatToStr(fa);
end;

procedure TForm1.SpinEdit2Change(Sender: TObject);
var b,fb,a1,a2,a3,a4,a5,ao:single;
begin
b:=spinedit2.value;
ao:=StrToFloat(Edit1.Text);
  a1:=StrToFloat(Edit2.Text);
  a2:=StrToFloat(Edit3.Text);
  a3:=StrToFloat(Edit4.Text);
  a4:=StrToFloat(Edit5.Text);
  a5:=StrToFloat(Edit6.Text);
 fb:=(a5*b*b*b*b*b)+(a4*b*b*b*b)+(a3*b*b*b)+(a2*b*b)+(a1*b)+ao;
 Edit9.Text:=FloatToStr(fb);
end;

end.

Kann mir jemand sagen, wieso das jetzt nicht hinhaut?!

Moderiert von user profile iconTino: Code-Tags hinzugefügt.


Popov - Sa 08.03.03 20:25

Ich sehe da ein mathematisches Problem. Irgendwie hab ich das Gefühl, daß du es durch Versuchen probierst. Sowas berechnet man.

Ansonsten sehe ich da so viele Fehler drinn, daß es kaum lohnt den Code zu verbessern. Der Aufwand ist kleiner es neu zu schreiben (und richtig).

Außerdem könnte man es besser lesen wenn du es in Code-Tags eingepackt hättest.


Popov - Sa 08.03.03 20:33

Übrigens ist das ein sehr schönes Beispiel wieso man keine GoTo's benutzen sollte. Man blickt da kaum durch.


VirusX - Sa 08.03.03 21:11

1. Wo siehst du da das mathematische Problem?
2. In dem Beispiel sind ganze 3 goto's, wieso ist das so schwer durchzublicken?
3. Find ich ja toll, dass du's mit sicherheit besser kannst, aber ich eben nicht.
4. Ist das ganze etwa so unübersichtlich wie du's darstellst?!
5. Hat ich eigentlich auf Hilfe gehofft, deine Postings, Popov, haben mir sehr wenig geholfen.

Moderiert von user profile iconTino: ICQ-Hinweis entfernt. Antworten nur hier ins Forum. Siehe Richtlinien.


Christian S. - Sa 08.03.03 21:25

Also, das Problem hat mich so interessiert, dass ich es (glaube ich) gelöst habe. Allerdings ist nicht ganz leicht.

Erstmal der Code. Und: ja, er ist eigentlich zu lang zum posten, aber er soll auch künftigen Lesern dieses Thread erhalten bleiben, deswegen kein Download oder so:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
var
  Form1: TForm1;
  a : Array[0..5] Of Real;
  startpunkt : Array[0..4] OF Real;
  nullstelle : ARRAY[0..4] OF Real;
  eingabe : Array[0..5] Of TEdit;
  max, min : Real;

implementation

{$R *.dfm}

function potenz (basis : Real; exponent : Integer) : Real;  //damit wir uns Math sparen können
VAR ergebnis : Real;
begin
  if exponent = 1 then result:=basis
  else begin
    if exponent = 0 then result:=1
    else begin
      if exponent mod 2 = 0 then
      begin
        ergebnis:=potenz(basis, exponent div 2);
        result:=ergebnis*ergebnis;
      end else result:=potenz(basis, exponent-1)*basis;
    end;
  end;
end;

function f(x : Real) : Real;  //Die FUnktion
VAR i : INTEGER;
begin
  result:=0;
  for i:=0 TO 5 DO
    result:=result+a[i]*potenz(x,i);
end;

function diff_f(x : Real) : Real;   //1. Ableitung der Funktion
VAR i : INTEGER;
begin
  result:=0;
  for i:=1 TO 5 DO
    result:=result+i*a[i]*potenz(x,i-1);
end;

procedure TForm1.FormCreate(Sender: TObject);
VAR i : INTEGER;
begin
  for i:=0 TO 5 DO
  begin
    eingabe[i]:=TEdit.Create(self);
    with eingabe[i] do
    begin
      Parent:=Form1;
      height:=21;
      width:=73;
      left:=(width+10)*i+10;
      top:=8;
      name:='eingabe'+IntToStr(i);
      text:=IntToStr(i+3);
    end;
  end;
end;

function nullstelle_berechnen(genauigkeit, start : Real) :Real;  //Newton'sches Annäherungsverfahren
VAR x_neu,x_alt : Real;
    stop, fehler : Boolean;
begin
  x_neu:=start;
  stop:=false;
  fehler:=false;
  while not stop do
  begin
    x_alt:=x_neu;
    x_neu:=x_alt-f(x_alt)/diff_f(x_alt);
    if abs(x_neu-x_alt)<=genauigkeit then stop:=true;
    if (Abs(max)-Abs(x_neu)<genauigkeit) or (Abs(min)-Abs(x_neu)<genauigkeit) then  //noch im Bereich?
    begin
      stop:=true;
      fehler:=true;
    end;
  end;
  if fehler then result:=max+1//Alle nicht verwendeten Felder, mit einem Wert ausserhalb
                              //des zulässigen Bereichs füllen, damit sie markiert sind.

  else result:=x_neu;
end;

procedure nullstellen_finden (genauigkeit : Real);
VAR i: Integer;
begin
  for i:=0 to 4 do
    if startpunkt[i]<=max then nullstelle[i]:=nullstelle_berechnen(genauigkeit, startpunkt[i])
    else nullstelle[i]:=max+1;
end;

procedure startpunkte_finden (schrittweite : Real);
VAR i : INTEGER;
    gefunden : Integer;
    x_left, alt_x_left : Real;
    x_right, alt_x_right : Real;
begin
  gefunden:=0;
  alt_x_left:=(max+min)/2;
  alt_x_right:=(max+min)/2;
  schrittweite:=abs(schrittweite);
  x_left:=alt_x_left-schrittweite;
  x_right:=alt_x_right+schrittweite;

  while (gefunden <= 4) and (Abs(max)-Abs(x_right)>(-schrittweite)) and (Abs(min)-Abs(x_left)>(-schrittweite)) do
  begin
    if Abs(max)-Abs(x_right)>(-schrittweite) then //noch im Bereich?
    begin
      if f(x_right) = 0 then   //direkt schon die Nullstelle gefunden
      begin
        startpunkt[gefunden]:=x_right;
        inc(gefunden);
      end;
      if (f(x_right)>0) and (f(alt_x_right)<0) then  //Vorzeichenwechsel
      begin
        startpunkt[gefunden]:=(x_right+alt_x_right)/2;
        inc(gefunden);
      end;

      if (f(x_right)<0) and (f(alt_x_right)>0) then  //Vorzeichenwechsel
      begin
        startpunkt[gefunden]:=(x_right+alt_x_right)/2;
        inc(gefunden);
      end;
      alt_x_right:=x_right;
      x_right:=x_right+schrittweite;
    end;


    if Abs(min)-Abs(x_left)>(-schrittweite) then  //noch im Bereich?
    begin
      if f(x_left) = 0 then        //direkt schon die Nullstelle gefunden
      begin
        startpunkt[gefunden]:=x_left;
        inc(gefunden);

      end else
      if (f(x_left)>0) and (f(alt_x_left)<0) then  //Vorzeichenwechsel
      begin
        startpunkt[gefunden]:=(x_left+alt_x_left)/2;
        inc(gefunden);
      end;

      if (f(x_left)<0) and (f(alt_x_left)>0) then  //Vorzeichenwechsel
      begin
        startpunkt[gefunden]:=(x_left+alt_x_left)/2;
        inc(gefunden);
      end;
      alt_x_left:=x_left;
      x_left:=x_left-schrittweite;
    end;
    Application.ProcessMessages;
  end;
  for i:=gefunden TO 4 DO startpunkt[i]:=max+1;  //Alle nicht verwendeten Felder, mit einem Wert ausserhalb
                                                 //des zulässigen Bereichs füllen, damit sie markiert sind.
end;

procedure TForm1.Button1Click(Sender: TObject);
VAR i : INTEGER;
begin
  max:=StrToFLoat(edit1.text);  //Der Bereich wird festgelegt, damit das Programm nicht ins Leere laufen kann
  min:=StrToFLoat(edit2.text);

  if max<min then   //Maximum soll größer Minimum sein
  begin
    max:=min;
    min:=StrToFloat(edit1.text);
  end;

  memo1.Lines.Clear;
  for i:=0 TO 5 DO a[i]:=StrToFloat(eingabe[i].Text);

  startpunkte_finden(0.001);  //Newton'sches Annäherungsverfahren funktioniert nur in der Umgebung der Nullstellen

  memo1.lines.add('STARTPUNKTE:');
  for i:=0 TO 4 DO
  if startpunkt[i]<=max then memo1.lines.add(FloatToStrF(startpunkt[i],ffGeneral,10,10));

  nullstellen_finden(0.000001);
  memo1.lines.add('NULLSTELLEN:');
  for i:=0 TO 4 DO
  if nullstelle[i]<=max then memo1.Lines.Add(FloatToStrF(nullstelle[i],ffGeneral,10,10))
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
VAR i : INTEGER;
begin
  for i:=0 TO 5 DO eingabe[i].Free;
end;


Folgendes wird gemacht: der Benutzer gibt die Koeffizienten ein in der Reihenfolge a0 bis a5. (Ist übrigens gut zu erweitern, für größere Gleichungen, das Programm!) Dann gibt er einen Bereich ein, in dem nach Nullstellen gesucht werden soll. Das ist zur Sicherheit da, damit sich das Programm nicht irgendwie zu Tode sucht.
Dann werden erstmal Startpunkte für das Annäherungsverfahren gesucht. Das muss man machen, da das Newton'sche Annäherungsverfahren nur in der Umgebung der Nullstellen funktioniert. Sonst könnte es divergieren. Das würde aber auch nochmal durch den Bereich abgefangen.
Dann startet das Annäherungsverfahren für jeden der Startpunkte.
Fertig.

Ich habe das Programm noch nicht ausführlich getestet, aber der Ansatz sollte richtig sein.

MfG,
Peter


VirusX - Sa 08.03.03 22:25

Vielen Dank, Peter. Hast recht, ist etwas kompliziert, aber mit der Zeit werd ich schon durchsteigen.
Danke für deine Mühe!


Popov - Sa 08.03.03 22:26

Sorry, aber nicht jeder hat so große Lust wie Peter Lustig.

Der erste Schritt zu Lösung eines Problems ist den Code zu entwirren und alles übersichtlich zu machen. Aber trotz des Hinweises auf Codetags hast du es nicht gemacht und dich lieber beschwert.

Ich habs für dich gemacht. Vielleichts siehst du die Fehler jetzt selbst. Sie springen einem sofort ins Auge. Aber ich weß ja nicht auf was du mit deinen GoTo's hinauswillst.


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
procedure TForm1.Button1Click(Sender: TObject);
var
  a1,a2,a3,a4,a5,ao,fa,fb,fm,m:single;
  a,b,e:single;

label
  Wiederholung, Ende, Ausgabe;

begin 
  ao := StrToFloat(Edit1.Text);
  a1 := StrToFloat(Edit2.Text);
  a2 := StrToFloat(Edit3.Text);
  a3 := StrToFloat(Edit4.Text);
  a4 := StrToFloat(Edit5.Text);
  a5 := StrToFloat(Edit6.Text);

  a := spinedit1.value ;
  b := spinedit2.value;
  e := StrToFloat(Edit10.Text);

  fa := (a5*a*a*a*a*a)+(a4*a*a*a*a)+(a3*a*a*a)+(a2*a*a)+(a1*a)+ao;
  fb := (a5*b*b*b*b*b)+(a4*b*b*b*b)+(a3*b*b*b)+(a2*b*b)+(a1*b)+ao;

  if fa*fb > 0 then label10.Caption := 'Falsches Intervall' else Wiederholung:

  m := (a+b)/2;
  fm := (a5*m*m*m*m*m)+(a4*m*m*m*m)+(a3*m*m*m)+(a2*m*m)+(a1*m)+ao;
  if fa*fm <= 0 then b := m ;

  goto Ende;

  a := m;

  Ende:

  fm := a5*m*m*m*m*m+a4*m*m*m*m+a3*m*m*m+a2*m*m+a1*m+ao;

  if fm*fm <= e*e then goto Ausgabe else goto Wiederholung;

  Ausgabe:

  Edit6.Text := FloatToStr(m);
end; 

procedure TForm1.SpinEdit1Change(Sender: TObject); 
var
  a,fa,a1,a2,a3,a4,a5,ao:single;
begin
  a:=spinedit1.value ;
  ao:=StrToFloat(Edit1.Text);
  a1:=StrToFloat(Edit2.Text);
  a2:=StrToFloat(Edit3.Text);
  a3:=StrToFloat(Edit4.Text);
  a4:=StrToFloat(Edit5.Text);
  a5:=StrToFloat(Edit6.Text);

  fa := (a5*a*a*a*a*a)+(a4*a*a*a*a)+(a3*a*a*a)+(a2*a*a)+(a1*a)+ao;

  Edit8.Text := FloatToStr(fa);
end;

procedure TForm1.SpinEdit2Change(Sender: TObject); 
var
  b,fb,a1,a2,a3,a4,a5,ao:single;
begin
  b:=spinedit2.value;
  ao:=StrToFloat(Edit1.Text);
  a1:=StrToFloat(Edit2.Text);
  a2:=StrToFloat(Edit3.Text);
  a3:=StrToFloat(Edit4.Text);
  a4:=StrToFloat(Edit5.Text);
  a5:=StrToFloat(Edit6.Text);

  fb := (a5*b*b*b*b*b)+(a4*b*b*b*b)+(a3*b*b*b)+(a2*b*b)+(a1*b)+ao;

  Edit9.Text := FloatToStr(fb);
end;


Übrigens, wo hast du programmieren gelernt? Auf der Schreibmaschine?

Anscheinend ist für dich o das gleiche wie 0 (z.B. a1,a2,a3,a4,a5,ao:single). Hat zwar keine Auswirkung auf das Programm, aber sowas (o anstelle von 0) hat man früher auf der Schreibmaschine gemacht.

Mit Power kann man das noch übersichtlicher und fehlerfreier machen:


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
//uses Math;
function Fn(a5,a4,a3,a2,a1,ao,x:single): single;
begin
  Result := a5*Power(x,5)+a4*Power(x,4)+a3*Power(x,3)+a2*Power(x,2)+(a1*x)+ao;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  a1,a2,a3,a4,a5,ao,fa,fb,fm,m:single;
  a,b,e:single;

label
  Wiederholung, Ende, Ausgabe;

begin
  ao := StrToFloat(Edit1.Text);
  a1 := StrToFloat(Edit2.Text);
  a2 := StrToFloat(Edit3.Text);
  a3 := StrToFloat(Edit4.Text);
  a4 := StrToFloat(Edit5.Text);
  a5 := StrToFloat(Edit6.Text);

  a := spinedit1.value ;
  b := spinedit2.value;
  e := StrToFloat(Edit10.Text);

  fa := Fn(a5,a4,a3,a2,a1,ao,a);
  fb := Fn(a5,a4,a3,a2,a1,ao,b);

  if fa*fb > 0 then label10.Caption := 'Falsches Intervall' else Wiederholung:  //<

  m := (a+b)/2;
  fm := Fn(a5,a4,a3,a2,a1,ao,m);
  if fa*fm <= 0 then b := m ;

  goto Ende; //<

  a := m;

  Ende: //<

  fm := Fn(a5,a4,a3,a2,a1,ao,m);

  if fm*fm <= e*e then goto Ausgabe else goto Wiederholung;

  Ausgabe:

  Edit6.Text := FloatToStr(m);
end;


Christian S. - Sa 08.03.03 22:28

Ach ja, die Gotos, dazu wollte ich auch noch etwas sagen:

Gotos sollte man in Delphi nur dort einsetzen, wo sie die klare Struktur nicht verschleiern, für die Delphi so bekannt ist. Hier [http://www.delphi-forum.de/viewtopic.php?t=7005&highlight=goto] findest Du eine längere Diskussion zu dem Thema.

Für Anfänger sollte es heißen: "verwende in Delphi keine Gotos" weil es eine Angewohnheit ist, die man nur mit Erfahrung einsetzen sollte. Sonst kommt man in Teufels Küche.
Für Anfänger: "Gotos sind schlecht", "Gotos sind Spaghetti-Programmierung"

MfG,
Peter


Christian S. - Sa 08.03.03 22:32

Zitat:
Vielen Dank, Peter. Hast recht, ist etwas kompliziert, aber mit der Zeit werd ich schon durchsteigen.

Denke ich auch. Hoffe, die Lösung funktioniert!

MfG,
Peter


Popov - Sa 08.03.03 22:41

Wie gesagt sind da zu viele Fehler um richtig zu wissen was gemeint ist, aber so könnte man das ohne GoTo machen (wenn ich die Fehler richtig gedeutet habe):


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
procedure TForm1.Button1Click(Sender: TObject);
var
  a1,a2,a3,a4,a5,ao,fa,fb,fm,m:single;
  a,b,e:single;
begin
  ao := StrToFloat(Edit1.Text);
  a1 := StrToFloat(Edit2.Text);
  a2 := StrToFloat(Edit3.Text);
  a3 := StrToFloat(Edit4.Text);
  a4 := StrToFloat(Edit5.Text);
  a5 := StrToFloat(Edit6.Text);

  a := spinedit1.value ;
  b := spinedit2.value;
  e := StrToFloat(Edit10.Text);

  fa := Fn(a5,a4,a3,a2,a1,ao,a);
  fb := Fn(a5,a4,a3,a2,a1,ao,b);

  if fa*fb > 0 then label10.Caption := 'Falsches Intervall' else
  repeat
    m := (a+b)/2;
    fm := Fn(a5,a4,a3,a2,a1,ao,m);
    if fa*fm <= 0 then b := m ;

    a := m;

    fm := Fn(a5,a4,a3,a2,a1,ao,m);
  until fm*fm <= e*e;

  Edit6.Text := FloatToStr(m);
end;


Christian S. - Sa 08.03.03 23:10

@VirusX: Das mit dem fa*fb<0 ist 'ne gute Idee. So kann man die Abfrage mit dem Vorzeichenwechsel bei mir auch verkürzen.

MfG,
Peter

Moderiert von user profile iconTino: Absatz entfernt da es PN diskutiert wird.


Christian S. - Mo 10.03.03 20:00

So, nachdem wir Tino soviel Arbeit gemacht haben (Sorry!) noch ein produktiver Hinweis:

ich habe das Programm mal weiterentwickelt, so dass jetzt die Nullstellen von Polynomen mit beliebigem Grad berechnet werden können.

Das Ganze steht jetzt in der Open Source-Abteilung

MfG,
Peter