Einzelnen Beitrag anzeigen

Amateurprofi

Registriert seit: 17. Nov 2005
Ort: Hamburg
1.062 Beiträge
 
Delphi XE2 Professional
 
#27

AW: Unterschiedliche Ergebnisse beim Runden

  Alt 16. Aug 2017, 10:09
Hallo Richard,
Es ist ja schön, dass du dein Problem gelöst hast, wie in #20 gezeigt, aber es wäre doch noch etwas schöner, wenn auch geklärt worden wäre, was eigentlich das Problem war.
Leider hast du auf die direkte Frage in #4 "Welche Typen haben Zahl und Multi?" nicht geantwortet.
In den Screenshots konnte man sehen, dass Multi den Wert 10 und Zahl den Wert 0.075 hatte, wobei interessant gewesen wäre, wie der Wert 0.075 entstanden war.

In den vielen Themen wurde leider meist an deinem Problem vorbei geredet, denn mit den unterschiedlichen Methoden des Rundens hatte das nichts zu tun.

Das Problem ist, dass Zahlen, die in dezimaler Schreibweise exakt dargestellt werden können, in binärer Schreibweise nicht exakt darstellbar sind.

Ich hab mal geprüft, wie die Werte X=0.075 und 10*X in der FPU aussehen, wenn vorher X unterschiedliche Typen hat.
In der nachstehenden Tabelle seht ihr jeweils den Typ von X, den Wert in der FPU in dezimaler Darstellung mit 20 Nachkommstellen und den Speicherauszug des Wertes in der FPU.

Code:
CPU interne Darstellung von X=0.075, wobei X den jeweils angegebenen Typ hat:
Single   0.07500000298023223880  00 00 00 00 00 9A 99 99 FB 3F
Real48    0.07500000000004547470  00 00 00 9A 99 99 99 99 FB 3F
Double   0.07499999999999999720  00 98 99 99 99 99 99 99 FB 3F
Extended 0.07500000000000000000  9A 99 99 99 99 99 99 99 FB 3F

CPU interne Darstellung von 10 * X=0.075, wobei X den jeweils angegebenen Typ hat:
Single   0.75000002980232238800  00 00 00 00 80 00 00 C0 FE 3F
Real48    0.75000000000045474700  00 00 80 00 00 00 00 C0 FE 3F
Double   0.74999999999999997200  00 FE FF FF FF FF FF BF FE 3F
Extended 0.75000000000000000000  00 00 00 00 00 00 00 C0 FE 3F
Man sieht sehr schön, dass wenn 0.075 in einem Double gespeichert war, in der FPU daraus ein Wert wird, der geringfügig kleiner ist.
Das Gleiche passiert auch bei dem mit 10 multiplizierten Wert, der dann, auf 7 gerundet wird, und zwar unabhängig davon, welche Methode der Rundung verwendet wird.

Die Tabelle wurde mit der nachstehenden Routine erstellt:
Delphi-Quellcode:
PROCEDURE TestRounding;
type TTBA=Array[0..9] of Byte;
PROCEDURE Store(Value:Extended; Typ:String; var S:String);
var I:Integer; T:String;
begin
   Str(Value:0:20,T);
   S:=S+#13#10+Typ+' '+T+' ';
   for I:=0 to 9 do S:=S+' '+IntToHex(TTBA(Value)[I],2);
end;
const
   H1='CPU interne Darstellung von X=0.075, wobei X den jeweils angegebenen Typ hat:';
   H2='CPU interne Darstellung von 10 * X=0.075, wobei X den jeweils angegebenen Typ hat:';
   ZahlS:Single=0.075;
   ZahlR:Real48=0.075;
   ZahlD:Double=0.075;
   ZahlE:Extended=0.075;
var I:Integer; S:String;
begin
   S:=H1;
   Store(ZahlS,'Single ',S);
   Store(ZahlR,'Real48 ',S);
   Store(ZahlD,'Double ',S);
   Store(ZahlE,'Extended',S);
   S:=S+#13#10#13#10+H2;
   Store(10*ZahlS,'Single ',S);
   Store(10*ZahlR,'Real48 ',S);
   Store(10*ZahlD,'Double ',S);
   Store(10*ZahlE,'Extended',S);
   Clipboard.AsText:=S;
end;
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat