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
Nachkommastellen bei Double
-
- Beiträge: 2149
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Nachkommastellen bei Double
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
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
-
- 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
Lass doch im Hintergrunf den Double einfach Double.Filestring = '1,235' nach dem Laden mit StrToFloat steht inder Doublevariable 1,2349999999999999
Ich möchte aber nur 3 Nachkommastellen haben.
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
Mit Java und C/C++ sehe ich rot