Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#13

AW: System.Frac / System.Int / Math.SimpleRoundTo - komische Ergebnisse

  Alt 11. Jul 2023, 18:03
Im Grunde liegt es wohl eher an Rundungsfehlern bei der Verwendung von Fließkommazahlen.

eine 0,9 könnte genau 0,9000000000 sein, aber wenn sich das nicht genau darstellen lässt oder es bei der Berechnung nicht ganz genau rauskommt,
könnte es quasi 0,899999999999 aber auch 0,9000000000001 sein. (vereinfachtes Beispiel, damit man sieht, was ich meine)

Und dann liefert es nachfolgend eben auch andere Werte,
z.B. bei Trunc oder Int(0,899999999999 * 10) eben 8 anstatt 9.

https://de.wikipedia.org/wiki/Gleitkommazahl
https://de.wikipedia.org/wiki/Doppelte_Genauigkeit
https://de.wikipedia.org/wiki/IEEE_754
...




Bei mir geht's und es sind wirklich ganz genau 0,000000. (aber muß eben nicht)

Double und Extended
Code:
type MyFloat = Double; //Extended;

procedure TForm25.FormCreate(Sender: TObject);
procedure DebugLog(Val: MyFloat);
  begin
    var S := string.Create(' ', SizeOf(Val) * 2);
    BinToHex(@Val, PChar(S), Length(S)); // Val.Bytes[i] for 0..9

    { knallt beim zweiten Durchlauf
    S := S + ' / ' + Val.ToString
           + ' / s' + Val.Sign.ToString
           +   ' e' + Val.Exp.ToString
           +   ' f' + Val.Frac.ToString;
           + ' / e' + Val.Exponent.ToString
           +   ' f' + Val.Fraction.ToString
           +   ' m' + Val.Mantissa.ToString
    }

    S := S + ' / ' + Val.ToString;
    S := S + ' / s' + Val.Sign.ToString;
    S := S +   ' e' + Val.Exp.ToString;
    S := S +   ' f' + Val.Frac.ToString;
    S := S + ' / e' + Val.Exponent.ToString;
    try S := S + ' f' + Val.Fraction.ToString; except S := S + ' peng'; end; // k.A. was es gegen 1/3 hat
    try S := S + ' m' + Val.Mantissa.ToString; except S := S + ' peng'; end;

    OutputDebugString(PChar(S));
  end;
var
  Val, Frac, Frac2: MyFloat;
begin
  Val  := 22.649;             DebugLog(Val);   // A01A2FDD24A63640 / 22,649 / s0 e1027 f1871527120149152 / e4 f1,4155625      m6375126747519648
  Val  := Val * 100;          DebugLog(Val);   // CDCCCCCCCCB1A140 / 2264,9 / s0 e1034 f476968144129229 / e11 f1,105908203125 m4980567771499725
  Val  := System.Int(Val);    DebugLog(Val);   // 0000000000B0A140 / 2264   / s0 e1034 f474989023199232 / e11 f1,10546875     m4978588650569728
  Frac := System.Frac(Val);   DebugLog(Frac);  // 0000000000000000 / 0 / s0 e0 f0 / e0 f0 m0
  Frac2 := Frac * 10.0;        DebugLog(Frac2); // 0000000000000000 / 0 / s0 e0 f0 / e0 f0 m0
  Frac2 := System.Int(Frac2);  DebugLog(Frac2); // 0000000000000000 / 0 / s0 e0 f0 / e0 f0 m0
  // auch komisch:
  Frac2 := Frac * 10.0;        DebugLog(Frac2); // 0000000000000000 / 0 / s0 e0 f0 / e0 f0 m0
  Frac2 := System.Frac(Frac2); DebugLog(Frac2); // 0000000000000000 / 0 / s0 e0 f0 / e0 f0 m0

  Val  := 1 / 3;              DebugLog(Val);   // 555555555555D53F / 0,333333333333333 / s0 e1021 f1501199875790165 / e-2 peng peng
  Val  := 1 / 5;              DebugLog(Val);   // 9A9999999999C93F / 0,2               / s0 e1020 f2702159776422298 / e-3 f1,6 m7205759403792794
end;
$2B or not $2B

Geändert von himitsu (11. Jul 2023 um 18:13 Uhr)
  Mit Zitat antworten Zitat