Präzision mit Floats
- Niesi
- Lazarusforum e. V.
- Beiträge: 581
- Registriert: So 26. Jun 2016, 19:44
- OS, Lazarus, FPC: Linux Mint Cinnamon, Laz 3.9 Fpc 3.2.3 und allerlei mit FpcUpDeLuxe
- Kontaktdaten:
Präzision mit Floats
Moin,
ich weiß: Das Thema ist schon etliche Male durchgekaut worden, aber ich möchte hier doch noch mal fragen, ob es Wissen oder Ideen zu meinem Problem gibt.
Ich muss Übersetzungen von Planetenradsätzen vergleichen, dabei möchte ich den bestmöglichen Radsatz ermitteln. Leider ergibt die mangelhafte Genauigkeit einige Probleme - und ich verstehe es einfach nicht. Das Beispielprojekt hat sich in vier Tagen unterschiedlich intensivem Suchens nach einer Lösung so ergeben - im Moment sind es drei Übersetzungen, welche ich vergleiche und dann die herausbekommen möchte, welche am dichtesten an der geforderten Übersetzung ist. Dabei soll aber nur auf den oberen oder unteren Wert gegangen werden, wenn einer davon WIRKLICH dichter dran ist, bei Gleichstand soll die "mittlere" Lösung beibehalten werden.
Das klappt jedoch nicht, da teilweise die Berechnungen mit den Extended kleine schmutzige Abweichungen bekommen. Diese Abweichungen entstehen aber nicht bei allen Berechnungen - WARUM?
Die Übersetzungen (i_ZS, i_ZSup und i_ZSdown) werden ganz und gar sauber berechnet.
Bei den Deltas dagegen geht irgendetwas schief - aber was?
Wenn ich die geforderte Übersetzung nicht als Zahlenwert eingebe, sondern aus zwei Integers berechne, dann sind zwei Deltawerte "sauber", nur der dritte nicht. Wie kann das denn sein???
Ich würde mich sehr freuen, wenn Ihr dazu was sagen könnt oder Ideen habt.
ich weiß: Das Thema ist schon etliche Male durchgekaut worden, aber ich möchte hier doch noch mal fragen, ob es Wissen oder Ideen zu meinem Problem gibt.
Ich muss Übersetzungen von Planetenradsätzen vergleichen, dabei möchte ich den bestmöglichen Radsatz ermitteln. Leider ergibt die mangelhafte Genauigkeit einige Probleme - und ich verstehe es einfach nicht. Das Beispielprojekt hat sich in vier Tagen unterschiedlich intensivem Suchens nach einer Lösung so ergeben - im Moment sind es drei Übersetzungen, welche ich vergleiche und dann die herausbekommen möchte, welche am dichtesten an der geforderten Übersetzung ist. Dabei soll aber nur auf den oberen oder unteren Wert gegangen werden, wenn einer davon WIRKLICH dichter dran ist, bei Gleichstand soll die "mittlere" Lösung beibehalten werden.
Das klappt jedoch nicht, da teilweise die Berechnungen mit den Extended kleine schmutzige Abweichungen bekommen. Diese Abweichungen entstehen aber nicht bei allen Berechnungen - WARUM?
Die Übersetzungen (i_ZS, i_ZSup und i_ZSdown) werden ganz und gar sauber berechnet.
Bei den Deltas dagegen geht irgendetwas schief - aber was?
Wenn ich die geforderte Übersetzung nicht als Zahlenwert eingebe, sondern aus zwei Integers berechne, dann sind zwei Deltawerte "sauber", nur der dritte nicht. Wie kann das denn sein???
Ich würde mich sehr freuen, wenn Ihr dazu was sagen könnt oder Ideen habt.
Wissen ist das einzige Gut, das sich vermehrt, wenn es geteilt wird ...
- Niesi
- Lazarusforum e. V.
- Beiträge: 581
- Registriert: So 26. Jun 2016, 19:44
- OS, Lazarus, FPC: Linux Mint Cinnamon, Laz 3.9 Fpc 3.2.3 und allerlei mit FpcUpDeLuxe
- Kontaktdaten:
Re: Präzision mit Floats
die Funktion abs() hatte ich auch schon verdächtigt, aber die hat keinen Einfluss ...
Wissen ist das einzige Gut, das sich vermehrt, wenn es geteilt wird ...
-
- Lazarusforum e. V.
- Beiträge: 280
- Registriert: Sa 26. Mai 2012, 17:31
- OS, Lazarus, FPC: Win 10 (L 2.2.6 x64 FPC 3.2.2)
- CPU-Target: 64Bit
Re: Präzision mit Floats
ähem...
ich hatte abs() entfernt und schon waren die Werte passig...
unter Windows 64bit.
Abs() verwendet direkte Registerzugriffe, da ist es womöglich sehr hardwareabhängig.
ich hatte abs() entfernt und schon waren die Werte passig...
unter Windows 64bit.
Abs() verwendet direkte Registerzugriffe, da ist es womöglich sehr hardwareabhängig.
just my two Beer
-
- Lazarusforum e. V.
- Beiträge: 280
- Registriert: Sa 26. Mai 2012, 17:31
- OS, Lazarus, FPC: Win 10 (L 2.2.6 x64 FPC 3.2.2)
- CPU-Target: 64Bit
Re: Präzision mit Floats
Hier wird mir die Ausgabe-Form gar nicht angezeigt.
- Niesi
- Lazarusforum e. V.
- Beiträge: 581
- Registriert: So 26. Jun 2016, 19:44
- OS, Lazarus, FPC: Linux Mint Cinnamon, Laz 3.9 Fpc 3.2.3 und allerlei mit FpcUpDeLuxe
- Kontaktdaten:
Re: Präzision mit Floats
Merkwürdig - ich lade es noch mal hoch. Ich hatte abs() auch entfernt, es ergab aber keinen Unterschied. Im Moment habe ich kein Lazarus unter Windows bereit.
Mein System ist
Ausgabe ist :
Wissen ist das einzige Gut, das sich vermehrt, wenn es geteilt wird ...
-
- Lazarusforum e. V.
- Beiträge: 280
- Registriert: Sa 26. Mai 2012, 17:31
- OS, Lazarus, FPC: Win 10 (L 2.2.6 x64 FPC 3.2.2)
- CPU-Target: 64Bit
Re: Präzision mit Floats
Ich habe das Fenster von Version 06 um den Zusatzcode von Version 07 ergänzt...
anders, aber auch mit NKs.
PS: In deiner Ausgabe zu delta_up steht delta_down; ich habs mal markiert
anders, aber auch mit NKs.
PS: In deiner Ausgabe zu delta_up steht delta_down; ich habs mal markiert
just my two Beer
- Niesi
- Lazarusforum e. V.
- Beiträge: 581
- Registriert: So 26. Jun 2016, 19:44
- OS, Lazarus, FPC: Linux Mint Cinnamon, Laz 3.9 Fpc 3.2.3 und allerlei mit FpcUpDeLuxe
- Kontaktdaten:
Re: Präzision mit Floats
Moin, stimmt, da bae ich schlampig kopiert - die Berechnung war mit den richtigen Werten.Joh hat geschrieben: Fr 5. Jul 2024, 17:38 Ich habe das Fenster von Version 06 um den Zusatzcode von Version 07 ergänzt...
anders, aber auch mit NKs.
Ich werde mal Lazarus auf einen Windowsrechner bringen und schauen, was da rum kommt, sonst muss ich wohl doch noch die Sprache wechseln

Wissen ist das einzige Gut, das sich vermehrt, wenn es geteilt wird ...
- Niesi
- Lazarusforum e. V.
- Beiträge: 581
- Registriert: So 26. Jun 2016, 19:44
- OS, Lazarus, FPC: Linux Mint Cinnamon, Laz 3.9 Fpc 3.2.3 und allerlei mit FpcUpDeLuxe
- Kontaktdaten:
Re: Präzision mit Floats
So, nun das Ganze aus der Windows-Welt:
(Jetzt verstehe ich das mit dem Programmfenster - sorry,
war mir nicht bewusst, dass das Fenster aus den sichtbaren
Bereich rutschen kann wenn ich zwei Monitore benutze. Nun
hab ich es selbst erlebt ...
)
Aber nun zum Kernproblem zurück:
Unter Windows wird in diesem Beispiel nur ein Wert mit Abweichung berechnet ...
Weiß jemand, ob die auftretende Ungenauigkeit am Pascal Compiler liegt?
(Jetzt verstehe ich das mit dem Programmfenster - sorry,
war mir nicht bewusst, dass das Fenster aus den sichtbaren
Bereich rutschen kann wenn ich zwei Monitore benutze. Nun
hab ich es selbst erlebt ...

Aber nun zum Kernproblem zurück:
Unter Windows wird in diesem Beispiel nur ein Wert mit Abweichung berechnet ...

Weiß jemand, ob die auftretende Ungenauigkeit am Pascal Compiler liegt?
Wissen ist das einzige Gut, das sich vermehrt, wenn es geteilt wird ...
- af0815
- Lazarusforum e. V.
- Beiträge: 6763
- Registriert: So 7. Jan 2007, 10:20
- OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
- CPU-Target: 32Bit (64Bit)
- Wohnort: Burgenland
- Kontaktdaten:
Re: Präzision mit Floats
Hast du dir bei deinem Problem eigentlich schon überlegt wieweit die Nachkommastellen von Relevanz sind ? Fliesskommawerte können nicht alle Zahlen über ihre Grenzen hinaus genau abblilden. Das sieht man auch an deinen Ausgaben. Nur welche Relevanz hat eine technisch gegeben Ungenauigkeit in der zB. 20zigsten Stelle.
Auch ein genauer Vergleich von solchen Zahlen ohne Berücksichtigung der Relevanz ist ganz einfach Problematisch. Ich glaube corpsmann und wp haben dazu hier im Forum einiges geschrieben.
Noch was, laut hier https://wiki.lazarus.freepascal.org/IEEE_754_formats ist extended 80 Bit, ABER NICHT auf allen Plattformen, weil 80 Bit auf etlichen Plattformen auf 64 Bit gemappt werden)
Auch ein genauer Vergleich von solchen Zahlen ohne Berücksichtigung der Relevanz ist ganz einfach Problematisch. Ich glaube corpsmann und wp haben dazu hier im Forum einiges geschrieben.
Noch was, laut hier https://wiki.lazarus.freepascal.org/IEEE_754_formats ist extended 80 Bit, ABER NICHT auf allen Plattformen, weil 80 Bit auf etlichen Plattformen auf 64 Bit gemappt werden)
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).
- Niesi
- Lazarusforum e. V.
- Beiträge: 581
- Registriert: So 26. Jun 2016, 19:44
- OS, Lazarus, FPC: Linux Mint Cinnamon, Laz 3.9 Fpc 3.2.3 und allerlei mit FpcUpDeLuxe
- Kontaktdaten:
Re: Präzision mit Floats
Ja, habe ich - im Prinzip reichen mir 3 bis max. 4 Nachkommastellen in dieser Anwendung aus. Das sind dann tausendstel bis zehntausendstel Millimeter. Drüber gestolpert bin ich, weil ich die Zahlenwerte vergleiche und falsche Ergebnisse bekam. (Zähnezahlen sollten nur geändert werden, wenn der eine Wert kleiner ist. Sie waren genau gleich, aber durch den Fehler wurde trotzdem gewechselt.)af0815 hat geschrieben: Sa 6. Jul 2024, 09:38 Hast du dir bei deinem Problem eigentlich schon überlegt wieweit die Nachkommastellen von Relevanz sind ? Fliesskommawerte können nicht alle Zahlen über ihre Grenzen hinaus genau abblilden. Das sieht man auch an deinen Ausgaben. Nur welche Relevanz hat eine technisch gegeben Ungenauigkeit in der zB. 20zigsten Stelle.
Auch ein genauer Vergleich von solchen Zahlen ohne Berücksichtigung der Relevanz ist ganz einfach Problematisch. Ich glaube corpsmann und wp haben dazu hier im Forum einiges geschrieben.
Noch was, laut hier https://wiki.lazarus.freepascal.org/IEEE_754_formats ist extended 80 Bit, ABER NICHT auf allen Plattformen, weil 80 Bit auf etlichen Plattformen auf 64 Bit gemappt werden)
Dazu kommt, dass es keine Rundungsfehler sind - die Ergebnisse sind ohne Rest. es wäre möglich, die Berechnung auch mit Integerwerten auszuführen, indem alles mit dem Faktor 1000 versehen wird. (Ist aber auch nur bei diesen speziellen Zähnezahlen so, Zähnezahlen werden vorzugsweise als Primzahlen ausgeführt, da geht so etwas nicht.)
Und dass die Berechnungen mal sauber ausgeführt werden und mal nicht - das macht mich nervös.
Da wüsste ich gern mehr drüber ...
Wichtig ist für mich auch, ab welcher Stelle das auftreten kann - Floats sind ja letztendlich im Rechner Zahlen mit einer bestimmten Stellenzahl - je größer die Zahl, desto weniger Nachkommastellen, wenn ich jetzt nicht ganz daneben liege. Mein Erwartung ist, dass eine Zahl, die mit 19 Digits dargestellt wird, dann korrekt ist.
Die Beiträge von Corpsmann und wp kenne ich, habe ich gelesen und stimme denen auch zu.
Aber dass auch die Art und Weise, wie ich die Gleichungen im Quelltext programmiere, das Ergebnis beeinflusst, da wurde noch nicht drüber berichtet.
Wissen ist das einzige Gut, das sich vermehrt, wenn es geteilt wird ...
Re: Präzision mit Floats
Da steht in den Screenshots der wert 3.14. Soll das die Zahl pi sein? Wenn ja, warum rechnest du nicht mit dem genauen Wert, der in der Math-Unit definiert ist? Mit 3.14 darfst du dich nicht über ungenaue Ergebnisse wundern.
- Niesi
- Lazarusforum e. V.
- Beiträge: 581
- Registriert: So 26. Jun 2016, 19:44
- OS, Lazarus, FPC: Linux Mint Cinnamon, Laz 3.9 Fpc 3.2.3 und allerlei mit FpcUpDeLuxe
- Kontaktdaten:
Re: Präzision mit Floats
Nein, soll nicht pi sein. Die User geben eine Übersetzung sowie eine erlaubte Abweichung ein, die App sucht dazu einen Radsatz.wp_xyz hat geschrieben: Sa 6. Jul 2024, 10:16 Da steht in den Screenshots der wert 3.14. Soll das die Zahl pi sein? Wenn ja, warum rechnest du nicht mit dem genauen Wert, der in der Math-Unit definiert ist? Mit 3.14 darfst du dich nicht über ungenaue Ergebnisse wundern.
Zanräder haben immer ganze Zähnezahlen, zumindest am Anfang. Daher wird der verlangte Wert selten ganz genau getroffen. In diesem Fall werden zwei Radsätze mit 3,12 gefunden und verglichen. Der zuerst gefundene hat eine "bessere" Zähnezahl im Planetenrad, er soll nur ersetzt werden, wenn der nächste dichter an der geforderten Übersetzung ist. Er wurde aber ersetzt, obwohl rechnerisch beide eine Abweichung von exakt 0,02 haben ...
Wissen ist das einzige Gut, das sich vermehrt, wenn es geteilt wird ...
Re: Präzision mit Floats
Ich verstehe das Problem immer noch nicht. Wenn ich mir die Screenshots ansehe, zeigen sie für mich alle dasselbe an, von den Rundungsfehlern abgesehen. Und wenn du nur 3-4 Nachkommastellen brauchst, sind die lächerlich klein.
P.S. In der Erklärungsspalte deines Memo-Output für delta_up steht i_ZsDown, was ja wohl nicht so sein sollte (sondern i_ZsUp), oder?
P.P.S. Falls es um die Rundungsfehler-Nachkommastellen geht: Führe einen Datentyp "float" (= extended, double, oder sogar single) ein, damit hast du mehr Flexibilität. Und lass dir mal die volle Auflösung anzeigen:
P.S. In der Erklärungsspalte deines Memo-Output für delta_up steht i_ZsDown, was ja wohl nicht so sein sollte (sondern i_ZsUp), oder?
P.P.S. Falls es um die Rundungsfehler-Nachkommastellen geht: Führe einen Datentyp "float" (= extended, double, oder sogar single) ein, damit hast du mehr Flexibilität. Und lass dir mal die volle Auflösung anzeigen:
Code: Alles auswählen
type
float = extended;
var
i_req, i_ZS, i_ZSup, i_ZSdown: float;
delta, delta_up, delta_down: float;
function FloatToStr(x: float): String;
begin
str(x, Result);
end;
- Niesi
- Lazarusforum e. V.
- Beiträge: 581
- Registriert: So 26. Jun 2016, 19:44
- OS, Lazarus, FPC: Linux Mint Cinnamon, Laz 3.9 Fpc 3.2.3 und allerlei mit FpcUpDeLuxe
- Kontaktdaten:
Re: Präzision mit Floats
Stimmt, indie Textausgabe hatte ich die falsche Berechnungszeile kopiert und dann nicht komplett korrigiert.wp_xyz hat geschrieben: Sa 6. Jul 2024, 12:02 Ich verstehe das Problem immer noch nicht. Wenn ich mir die Screenshots ansehe, zeigen sie für mich alle dasselbe an, von den Rundungsfehlern abgesehen. Und wenn du nur 3-4 Nachkommastellen brauchst, sind die lächerlich klein.
P.S. In der Erklärungsspalte deines Memo-Output für delta_up steht i_ZsDown, was ja wohl nicht so sein sollte (sondern i_ZsUp), oder?
P.P.S. Falls es um die Rundungsfehler-Nachkommastellen geht: Führe einen Datentyp "float" (= extended, double, oder sogar single) ein, damit hast du mehr Flexibilität. Und lass dir mal die volle Auflösung anzeigen:Code: Alles auswählen
type float = extended; var i_req, i_ZS, i_ZSup, i_ZSdown: float; delta, delta_up, delta_down: float; function FloatToStr(x: float): String; begin str(x, Result); end;

Sorry dafür.
Der Quelltext für die Berechnung war stets korrekt.
Noch einmal zu meinem Problem: Ich vergleiche zwei delta (delta und delta_up), welche mathematisch ganz genau beide eine Abweichung von 0,02 darstellen. In dem Fall sollen keine Änderungen vorgenommen werden.
Da aber delta = 0.0200000000000001 und delta_up = 0.0199999999999999
als Ergebnis geliefert werden, ist beim Vergleich delta_up kleiner als delta.
Das führt dazu, dass Zähnezahlen geändert werden.
Und das ist dann Mist.
Mit meinem kleinen Beispiel wollte ich nur demonstrieren, dass es diese Abweichungen gibt und dass durch verändern des Berechnungsweges der Fehler manchmal verschwindet.
Es ist auch irgendwie kein Rundungsfehler, 3.12 und 3.14 sind beide glatt teilbar.
Ich kann mir schon mit RoundTo helfen. Getriebe sind meist nicht mit so großen Zahlen behaftet - aber was ist mit Apps für die Astronomie? Schwanken dann die Entfernungen um einige Lichtjahre, je nachdem, wie die Berechnung programmiert wird?
Ganz konkret:
Mit dem folgenden Code werden alle drei delta falsch.
Code: Alles auswählen
begin
i_req := 3.14;
z_H := -54;
z_Z := 25;
i_ZS := 1 - z_H / z_Z;
i_ZSup := 1 - (z_H + 1) / z_Z;
i_ZSdown := 1 - (z_H - 1) / z_Z;
delta := abs(i_req - i_ZS);
delta_up := abs(i_req - i_ZSup);
delta_down := abs(i_req - i_ZSdown);
with MyMemo.Lines do
begin
add(' - - - - - - - - - - - - - - - - - - - - - - - - -');
add(' z_Z, z_H und i_req als input:');
add(' Eingabewert: z_Z = ' + IntToStr(z_Z));
add(' Eingabewert: z_H = ' + IntToStr(z_H));
add(' Eingabewert: i_req = ' + FloatToStr(i_req));
add(' ');
add(' i_ZS := 1 - z_H / z_Z; = i_ZS = ' + FloatToStr(i_ZS));
add(' i_ZSup := 1 - (z_H + 1) / z_Z; = i_ZSup = ' + FloatToStr(i_ZSup));
add(' i_ZSdown := 1 - (z_H - 1) / z_Z; = i_ZSdown = ' + FloatToStr(i_ZSdown));
add(' delta := abs(i_req - i_ZS); = delta = ' + FloatToStr(delta));
add(' delta_up := abs(i_req - i_ZSup); = delta_up = ' + FloatToStr(delta_up));
add(' delta_down := abs(i_req - i_ZSdown); = delta_down = ' + FloatToStr(delta_down));
add(' ');
end;
Code: Alles auswählen
i_reqBuff := 314;
i_req := i_reqBuff / 100;
i_ZS := 1 - z_H / z_Z;
i_ZSup := 1 - (z_H + 1) / z_Z;
i_ZSdown := 1 - (z_H - 1) / z_Z;
delta := abs(i_req - i_ZS);
delta_up := abs(i_req - i_ZSup);
delta_down := abs(i_req - i_ZSdown);
with MyMemo.Lines do
begin
add(' - - - - - - - - - - - - - - - - - - - - - - - - -');
add(' z_Z, z_H als input; i_req berechnet:');
add(' Eingabewert: z_Z = ' + IntToStr(z_Z));
add(' Eingabewert: z_H = ' + IntToStr(z_H));
add(' ');
add(' i_req := 314 / 100 = i_req = ' + FloatToStr(i_req));
add(' ');
add(' i_ZS := 1 - z_H / z_Z; = i_ZS = ' + FloatToStr(i_ZS));
add(' i_ZSup := 1 - (z_H + 1) / z_Z; = i_ZSup = ' + FloatToStr(i_ZSup));
add(' i_ZSdown := 1 - (z_H - 1) / z_Z; = i_ZSdown = ' + FloatToStr(i_ZSdown));
add(' delta := abs(i_req - i_ZS); = delta = ' + FloatToStr(delta));
add(' delta_up := abs(i_req - i_ZSup); = delta_up = ' + FloatToStr(delta_up));
add(' delta_down := abs(i_req - i_ZSdown); = delta_down = ' + FloatToStr(delta_down));
add(' ');
end;
Im zweiten Fall berechne ich i_req mit 314 / 100.
Warum sind die Ergebnisse unterschiedlich?
Wissen ist das einzige Gut, das sich vermehrt, wenn es geteilt wird ...