Nachkommastellen bei Double

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
Benutzeravatar
juelin
Beiträge: 297
Registriert: Sa 24. Jul 2021, 18:03
OS, Lazarus, FPC: Linux Ubuntu 22. Windows 10 Delphi 11.3 (L 0.9.xy FPC 2.2.z)
CPU-Target: 64Bit
Wohnort: Mannheim

Nachkommastellen bei Double

Beitrag von juelin »

Hallo,
ich habe Windows 10 und Lazarus 3.6 mit FPC 3.2.2
Lese Daten aus einem File (String) und will sie in eine Double-Variable speichern.
Das klappt auch aber folgendes Problem:
Filestring = '1,235' nach dem Laden mit StrToFloat steht inder Doublevariable 1,2349999999999999
Ich möchte aber nur 3 Nachkommastellen haben.
Habe 3 Methoden ausbrobiert. (f1 und f2=Doublevariable
1. f1 := RoundTo(f1, -3);
2. f2 := Round(f1 * 1000); f1:=f2 / 1000;
3. f2 := f1; f1 := StrToFloat(FormatFloat('0,000', f2));
Haben aber alle drei nichts gebracht.
Hat Jemand noch eine Idee?
Danke und Gruß
Jürgen

Warf
Beiträge: 2149
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Nachkommastellen bei Double

Beitrag von Warf »

Das liegt schlicht weg daran das in einem Beliebigen Zahlensystem nicht alle Rationalen Zahlen endlich dargestellt werden können.

Wir verwenden das 10er System, die Primfaktorzerlegung von 10 ist 2 und 5, d.h. alle Zahlen die sich als Brüche von 2 und 5 darstellen lassen sind endlich darstellbar. Beispiel 1/2=0.5, 1/5=0.2, 1/10=1/(2*5)=0.1. Brüche deren Divisor Prifaktoren enthält die weder 2 noch 5 sind lassen sich nicht endlich darstellen. Z.B. 1/3=0.33333... d.h. an irgendeiner stelle muss gerundet werden,

Für den Computer ist das nicht anders, der arbeitet im Binärsystem, d.h. dieser kann lediglich Zahlen die als Brüche mit einem Divisor dessen Primfaktorzerlegung nur aus 2 besteht korrekt darstellen. Also 1/2=0.1 (binär) aber 1/5=0.0111110010011...

Die Zahl 1,235 = 1 + 1/5 + 3/(2*5*2*5) + 1/(2*2*5*2*5). Weil an mehreren stellen hier der Divisor 5 vorkommt ist es schlicht weg technisch nicht möglich diese genau im Rechner darzustellen. Was du brauchst wenn du diese Genauigkeit haben willst ist Fixpunktrechnung. Dabei rechnest du in ganzen Zahlen und wendest den Divisor selbst an. Somit kannst du einen beliebigen Divisor, z.B. 10 nehmen, ohne auf das Binärsystem von Fließkommazahlen forciert zu werden.

Der standard Datentyp um dies in Pascal zu machen ist eigentlich Currency, aber, ich kenn den aktuellen Stand davon nicht, aber früher war auf 32 bit Currency kaputt und hat einfach auf Floats gemapped

Mathias
Beiträge: 6969
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Nachkommastellen bei Double

Beitrag von Mathias »

Filestring = '1,235' nach dem Laden mit StrToFloat steht inder Doublevariable 1,2349999999999999
Ich möchte aber nur 3 Nachkommastellen haben.
Lass doch im Hintergrunf den Double einfach Double.
Für die Ausgabe schneidest dann auf deine 3 Stellen.

Ich mache dies für eine einfache Ausgabe immer so:

Code: Alles auswählen

var
  d: double = 1.2349999999999999;
begin
  WriteLn(d: 6: 3);  // -> 1.235
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Antworten