fliegermichl hat geschrieben: Mi 23. Aug 2023, 08:20
Was ich mich frage ist, SizeOf(d) ergibt sowohl im 32 als auch im 64 Bit Programm 8.
Ja aber das = hat 2 Seiten, wenn d auf beiden Seiten gleich ist dann liegt der Unterschied wohl in der konstanten
fliegermichl hat geschrieben: Mi 23. Aug 2023, 08:20
Ich habe mir dann auch den Wert mittels Format('%g', [d]) ausgeben lassen und da spuckt das 32 Bit Programm -0.20000000000000001 und das 64 Bit -0.2 aus.
Schau dir Mal den source von Format an
Code: Alles auswählen
'G' : begin
if CheckArg(vtCurrency,false) then
ToAdd:=TFormatString(FloatToStrF(Args[doarg].VCurrency^,ffGeneral,Prec,3,FormatSettings))
else if CheckArg(vtExtended,true) then
ToAdd:=TFormatString(FloatToStrF(Args[doarg].VExtended^,ffGeneral,Prec,3,FormatSettings));
end;
Das benutzt intern entweder extended oder currency, beides Typen die auf 32 und 64 bit sich anders verhalten.
Zu deinem Problem, also das Ding ist Recht einfach, floats, egal ob single, double oder extended length floats können, da es sich um das binär Zahlensystem handelt, nur zahlen die sich als Summe von 2er Potenzen zusammensetzen genau darstellen, also sowas wie 0,5 (2^-1), 0,25 (2^-2) oder 0,75 (0,5 + 0,25).
In der realen Welt benutzen wir aber das 10er system, und da 10=2*5 ist können wir alle zahlen darstellen die sich als Summen und produkt aus 2er und 5er Potenzen darstellen lassen, also z.b. 0,2 (5^-1) oder 0,1 (0,2 * 0,5).
Deshalb kannst du 0,2 niemals genau darstellen und jede Darstellung ist eine Rundung.
In deinem Beispiel wird jetzt für d die 48 Bit Rundung von 0.2 genommen, weil double eine 48 Bit mantisse hat. Für die konstante 0.2 in der Gleichung wird dann aber für 32 Bit ein anderer Typ genommen, entweder single mit 24 bit Rundung oder extended mit 64 bit. Egal ob mehr oder weniger Genauigkeit, die Rundung ist anders und kann nicht unbedingt trivial verglichen werden
Die Lösung wie bereits schon erwähnt ist für das spezielle Beispiel der Cast der konstante auf Double und damit auf die selbe 48 Bit Rundung. Das ist natürlich aber nur ein fix für dieses spezielle Beispiel, das folgende sollte trotzdem kaputt gehen
Denn der Rundungsfehler akkumuliert sich über arithmetische Operationen.
Allerdings sollte das dann auf 32 und 64 bit genauso schief gehen, also immerhin konsistentes Verhalten
Eine wirkliche Lösung ist einfach nicht = für floats zu verwenden, sondern nur <= und >= (wie SameValue es tut), oder noch besser, einfach keine floats verwenden sondern fixpunkt und direkt korrekt rechnen ohne Rundungsfehler