| Autor |
Beitrag |
jjturbo
      
Beiträge: 516
Win2000 prof., WinXP prof.
D4 Stand., D5 Prof, D7 Prof, D2007 Prof.
|
Verfasst: Mo 20.06.05 10:05
Moin Forum,
ich habe ein Problem mit einer Schleife in einem älteren Projekt.
Die u. a. Schleife bricht zu spät ab, sie führt eine Berechnung zu viel aus.
ABER: Das passiert nur auf einem bestimmten Rechner(älteres Modell, ca. 4Jahre alt). Auf mehreren anderen gehts...
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| procedure RechneIrgenwas; const WerkzeugGesamtHoehe = 34.5; var fertig :Boolean; Nr :Integer; PosZ :Array[0..50] of Real; begin
fertig := false; Nr := 0;
while not fertig do begin PosZ[Nr]:=PosZ[Nr-1] + WerkzeugGesamtHoehe; if PosZ[Nr] >= 200 then fertig := True; inc(Nr); end;
end; |
Gibt es dafür einen bestimmten Grund?
Dank euch, jjturbo Moderiert von Christian S.: Topic aus VCL (Visual Component Library) verschoben am Mi 22.06.2005 um 09:47
_________________ Windows XP: Für die einen nur ein Betriebssystem - für die anderen der längste Virus der Welt...
|
|
Sprint
      
Beiträge: 849
|
Verfasst: Mo 20.06.05 10:11
Delphi-Quelltext 1:
| PosZ[Nr]:=PosZ[Nr-1] + WerkzeugGesamtHoehe; |
Erster Durchlauf PosZ[0]:=PosZ[-1] + WerkzeugGesamtHoehe;
Dein Array PosZ geht aber nur von 0 bis 50. -1 gibt es nicht.
Außerdem musst du, wenn Nr > 50 ist, aus der Schleife springen.
_________________ Ciao, Sprint.
|
|
Tana´Ri
      
Beiträge: 230
|
Verfasst: Mo 20.06.05 10:13
verwend doch mal eine BREAK zum verlassen der Schleife, vielleicht
funktionierts.
Außerdem könnte dein NR ne Bereichsverletzung verursachen, da du
die limierte Array-Dimension nicht berücksichtigst.
Und Wann ein Array-Element nun einen Wert größer oder gleich 200
hat ist ja auch fraglich (theoretisch nie!!!), denn er ist ja auch
nicht vorinitialisiert - d.h. gelesene Werte sind fraglich.
_________________ mfg
Tana´Ri
|
|
jjturbo 
      
Beiträge: 516
Win2000 prof., WinXP prof.
D4 Stand., D5 Prof, D7 Prof, D2007 Prof.
|
Verfasst: Mo 20.06.05 10:23
Das ist natürlich nur ein Beispiel. Im Originalprogramm sind die Variablen initialisiert worden und das Array wird nur in gültigen Bereichen angesprochen.
Mein Problem ist, das der Vergleich
Delphi-Quelltext 1:
| if PosZ[Nr] >= 200 then fertig := True; |
obwohl die Bedingung erfüllt ist, die Schleife nicht abbricht. Auf anderen Rechnern gehts aber.
_________________ Windows XP: Für die einen nur ein Betriebssystem - für die anderen der längste Virus der Welt...
|
|
Tana´Ri
      
Beiträge: 230
|
Verfasst: Mo 20.06.05 11:01
und worin unterscheidet sich dieses eine System (entscheiden ist normal die CPU, bestimmt Compilierungsverfahren).
[teste mal BREAK oder ne Fußgesteuerte Schleife (repeat until)]
_________________ mfg
Tana´Ri
|
|
jjturbo 
      
Beiträge: 516
Win2000 prof., WinXP prof.
D4 Stand., D5 Prof, D7 Prof, D2007 Prof.
|
Verfasst: Mo 20.06.05 11:06
Aber worin kann das Problem liegen? Die ältere CPU? Es gab doch mal welche mit irgendwelchen Rechenfehlern(Pentium I?)
_________________ Windows XP: Für die einen nur ein Betriebssystem - für die anderen der längste Virus der Welt...
|
|
Sprint
      
Beiträge: 849
|
Verfasst: Mo 20.06.05 11:06
Oder poste ein anständiges Beispiel. Am besten das, das auf dem Rechner nicht läuft.
_________________ Ciao, Sprint.
|
|
jjturbo 
      
Beiträge: 516
Win2000 prof., WinXP prof.
D4 Stand., D5 Prof, D7 Prof, D2007 Prof.
|
Verfasst: Mo 20.06.05 11:18
Das Beispiel entspricht schon dem Original. Dort sind die Variablen allerdings nicht alle lokal deklariert.
Ich habe auch mal die errechneten Werte jedes Schleifendurchlaufs protokollieren lassen und auf den verschiedenen Rechnern als Datei gespeichert um mir die Zwischenergebnisse anzusehen.
Die errechneten Werte sind alle gleich.
Zu einem bestimmten Zeitpunkt sollte der Vergleich " if 241 >= 241 then fertig := True" die Schleife doch zum Abbruch zwingen, oder?
Auf der "alten Kiste" wird die Schleife erst einen Durchlauf später abgebrochen.
hie mal zwei Protokolle, das erste ist OK, das zweite zeigt den Fehler:
------------------------------------------------------------------------
Protokoll 1:
1 Init: 1,5
2 Init: 7,98333333333333
3 Init: 30
4 Init: 241
5 Init: 71,85
6 PosZ1: 161,166666666667
7 PosZ1: 81,3333333333332
8 PosZ1: 1,49999999999992
9 PosZ2: 81,3333333333332
10 Vergl: 81,3333333333332 >= 241 ??? Dann Ende...
11 Anz: 3
12 PosZ2: 161,166666666667
13 Vergl: 161,166666666667 >= 241 ??? Dann Ende...
14 Anz: 4
15 PosZ2: 241
16 Vergl: 241 >= 241 ??? Dann Ende...
17 Anz: 5
------------------------------------------------------------------------
Protokoll 2
2 Init: 7,98333333333333
3 Init: 30
4 Init: 241
5 Init: 71,85
6 PosZ1: 161,166666666667
7 PosZ1: 81,3333333333332
8 PosZ1: 1,49999999999992
9 PosZ2: 81,3333333333332
10 Vergl: 81,3333333333332 >= 241 ??? Dann Ende...
11 Anz: 3
12 PosZ2: 161,166666666667
13 Vergl: 161,166666666667 >= 241 ??? Dann Ende...
14 Anz: 4
15 PosZ2: 241
16 Vergl: 241 >= 241 ??? Dann Ende...
17 Anz: 5
18 PosZ2: 320,833333333333
19 Vergl: 320,833333333333 >= 241 ??? Dann Ende...
20 Anz: 6
_________________ Windows XP: Für die einen nur ein Betriebssystem - für die anderen der längste Virus der Welt...
|
|
jjturbo 
      
Beiträge: 516
Win2000 prof., WinXP prof.
D4 Stand., D5 Prof, D7 Prof, D2007 Prof.
|
Verfasst: Mi 22.06.05 06:24
Ich habe jetzt mal versucht mit break die Schleife abzubrechen. Doch nach wie vor wird sie ein mal zuviel durchlaufen.
Irgendwie scheint der Vergleich nicht zu funktionieren.
Hat jemand eine Idee?
_________________ Windows XP: Für die einen nur ein Betriebssystem - für die anderen der längste Virus der Welt...
|
|
alzaimar
      
Beiträge: 2889
Erhaltene Danke: 13
W2000, XP
D6E, BDS2006A, DevExpress
|
Verfasst: Mi 22.06.05 07:07
Kein PC kann mit reelen Zahlen genau rechnen, das liegt einerseits in der Natur der reelen Zahlen, andererseits am Datenformat (floating point). Dieses Format kann z.B. '0.1' gar nicht genau darstellen. Test:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| Var r : Real;
Begin r:=-1; While r<1 do begin memo1.lines.add(floatToStr (r)); r := r + 0.1; End; End; |
In deinem Beispiel wird die 200 nicht genau getroffen. Das hängt auch von der CPU, genauer gesagt von der FPU ab. Wie rechnet die genau?
Wie Du an dem o.g. Test sehen wirst, wird die Zahl 0 nicht getroffen!
Du kannst z.B. prüfen, ob deine Zahl fast genau 200 ist, also z.B. mit
Quelltext 1:
| If Abs (Zahl - 200) < 1E-5 |
Eine andere Möglichkeit wäre, die Grenze von 200 auf 200+Schrittweite/2 zu erweitern.
Niemals bei reelen (floating point) Zahlen auf Gleichheit testen!
|
|
jjturbo 
      
Beiträge: 516
Win2000 prof., WinXP prof.
D4 Stand., D5 Prof, D7 Prof, D2007 Prof.
|
Verfasst: Mi 22.06.05 08:41
@alzaimar: Danke erst mal für Deine Ausführungen.
Ich hatte gestern mal folgendes ausprobiert, um diese "Ungenauigkeiten" zu umgehen.
Ich hatte
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| while not fertig do begin PosZ[Nr]:=PosZ[Nr-1] + WerkzeugGesamtHoehe; if abs(PosZ[Nr]) - abs(IrgendeinVergelichswert) < 0.01 then fertig := True; inc(Nr); end; |
Aber scheinbar ist auch das nicht Lösung.
Was mich aber sehr wundert: Dieser Programmteil hat früher funktioniert. Auf dem selben Rechner.
Was hat sich bisher geändert? Die Delphi-Version, mit der das Programm compiliert wurde(früher D4, jetzt D5), mein Notebook.
Auf dem Zielrechner läuft Windows NT4.0

_________________ Windows XP: Für die einen nur ein Betriebssystem - für die anderen der längste Virus der Welt...
|
|
|