(Gelöst) Float-/Realzahl auf Anzahl Nachkommastellen kürzen

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
GU_Meyer
Beiträge: 66
Registriert: Mo 21. Apr 2014, 10:22

(Gelöst) Float-/Realzahl auf Anzahl Nachkommastellen kürzen

Beitrag von GU_Meyer »

Hallo,
für mein Kartenprojekt (siehe andere Fragen dazu auch http://www.lazarusforum.de/viewtopic.php?f=25&t=8971 hier) brauche ich Koordinatenangaben als Real-Zahlen. Allerdings haben mir die Freepascal-Zahlen zuviele Nachkommastellen :wink: - ich brauche nur max. 6. Gibt es eine Function/Procedure, die mir eine gegebene Real-Zahl auf eine angegebene Anzahl Nachkommastellen "kürzt" oder auch gern rundet? Mit "trunc" kriege ich ja nur den Ganzzahl-Anteil.
Falls nicht, würde ich mir das über den Umweg eines Strings und anschließender Rückkonvertierung des gekürzten Strings selbst schreiben müssen - gefällt mir überhaupt nicht. :(

Gibts eine Lösung?
Danke und Gruss
GU_Meyer
Zuletzt geändert von GU_Meyer am Sa 12. Sep 2015, 23:04, insgesamt 1-mal geändert.

wp_xyz
Beiträge: 5152
Registriert: Fr 8. Apr 2011, 09:01

Re: Float-/Realzahl auf Anzahl Nachkommastellen kürzen

Beitrag von wp_xyz »

Na hoffentlich gelangen solche Karten mit gerundeten Koordinaten nie auf mein Navi...

Im Ernst: Warum willst du denn die Koordinaten runden? Ich verstehe richtig: die Zahlenwerte? Wenn du die Zahlenwerte veränderst, wird jede Rechnung, die darauf basiert, ungenau. Ich nehme an, du meinst die Stringausgabe der Zahlen. Dafür kannst du z.B. die Format-Funktion verwenden, oder FormatFloat:

Code: Alles auswählen

 
var
  x: Double;
  s: String;
begin
  s := Format('%.6f', [x]);                // die "6" ist die Anzahl der Nachkommastellen
  s := FormatFloat('0.000000', x);    
 

GU_Meyer
Beiträge: 66
Registriert: Mo 21. Apr 2014, 10:22

Re: Float-/Realzahl auf Anzahl Nachkommastellen kürzen

Beitrag von GU_Meyer »

wp_xyz hat geschrieben:Na hoffentlich gelangen solche Karten mit gerundeten Koordinaten nie auf mein Navi...
Keine Sorge, mir wäre es lieber, ich müsste nicht runden. Und ich brauche in meinem Fall die Koordinaten nach Möglichkeit sogar auf +-10m genau (genauer macht keinen Sinn, da es um GPS-Koordinaten, ermittelt im worst-case von einem Smartphone, geht).
wp_xyz hat geschrieben:Im Ernst: Warum willst du denn die Koordinaten runden? Ich verstehe richtig: die Zahlenwerte? Wenn du die Zahlenwerte veränderst, wird jede Rechnung, die darauf basiert, ungenau. Ich nehme an, du meinst die Stringausgabe der Zahlen. Dafür kannst du z.B. die Format-Funktion verwenden, oder FormatFloat:

Code: Alles auswählen

 
var
  x: Double;
  s: String;
begin
  s := Format('%.6f', [x]);                // die "6" ist die Anzahl der Nachkommastellen
  s := FormatFloat('0.000000', x);    
 
Fast richtig. Ich habe Koordinaten, die auf einer Karte anzeigen möchte. Allerdings sind diese Koordinaten nur max 6 Nachkommastellen lang (Beispiel: 48,29553). Leider macht mir Lazarus bei der Eingabe daraus dann 48.295529999999999 . Und wenn ich damit dann weiter rechne, um die Position auf meiner Karte zu ermitteln, erhalte ich ABweichungen der berechneten Werte zu den Soll-Werten. Deshalb komme ich auf der "Kürzen" der Nachkommastellen bzw. Runden. Mir ist schon klar, dass ich hier mit der internen Darstellung der Zahlenwerte "kämpfe", aber ich hatte auf einen Ausweg gehofft.
Gruss
GU_Meyer

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6780
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Float-/Realzahl auf Anzahl Nachkommastellen kürzen

Beitrag von af0815 »

Wenn du Probleme bei den Rundungen und den Ungenauigkeiten bei Floattypen bekommst, warum arbeitest du intern nicht mit Integer Datentypen und multipilierst bzw. dividierst ganz einfach mit 1.000.000. Dann bist du auf 6 Stellen genau. Bei Currency wird ja was ähnliches verwendet.

Longint -2147483648 .. 2147483647
Longword 0..4294967295 4
Int64 -9223372036854775808 .. 9223372036854775807

Siehe http://wiki.lazarus.freepascal.org/Vari ... Data_Types
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

wp_xyz
Beiträge: 5152
Registriert: Fr 8. Apr 2011, 09:01

Re: Float-/Realzahl auf Anzahl Nachkommastellen kürzen

Beitrag von wp_xyz »

GU_Meyer hat geschrieben:Leider macht mir Lazarus bei der Eingabe daraus dann 48.295529999999999 .
Das liegt in der Natur des Binärsystems: in der Mathematik liegen reelle Zahlen beliebig dicht, nicht aber im Binärsystem, da man, je nach Datentyp, nur eine begrenzte Anzahl von Bits zur Verfügung hat. Du kannst die Zahlenwerten runden wie du willst, auf 48.29553 wirst du nie exakt kommen, sonst hätte es dir Lazarus schon so angezeigt.

Nochmals: Du verwechselst die interne Zahlendarstellung als Double oder Extended mit 8 oder 10 bytes mit der Stringdarstellung. Mit den oben genannten Stringformatierungsfunktionen kannst du deine Zahl 48.295529999999999 problemlos in den String '48.29553' verwandeln, was in Karten, Listen, Tabellen etc vernünftig aussieht. Aber bitte: nie den gerundeten String in die Zahl zurück verwandeln und damit weiterrechnen, nimm die Originalzahl.

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Float-/Realzahl auf Anzahl Nachkommastellen kürzen

Beitrag von mschnell »

GU_Meyer hat geschrieben:Gibt es eine Function/Procedure, die mir eine gegebene Real-Zahl auf eine angegebene Anzahl Nachkommastellen "kürzt" oder auch gern rundet?
Das geht technisch nicht. Real-Zahlen rechnen mit binären Nachkomma-Stellen, nicht mit dezimalen. Die Zahl 0.1 ist als Real (oder Extended) gar nicht exakt darstellbar.

Wenn Du mit einer festen Nackkomma-Stellen-Zahl rechnen willst, nimmst Du am besten Integer (oder Int64, wenn nötig) und skalierst mit einem festen 10^n, denkst Dir das Komma also an einer bestimmten Stelle.

-Michael
Zuletzt geändert von mschnell am So 13. Sep 2015, 07:25, insgesamt 1-mal geändert.

GU_Meyer
Beiträge: 66
Registriert: Mo 21. Apr 2014, 10:22

Re: Float-/Realzahl auf Anzahl Nachkommastellen kürzen

Beitrag von GU_Meyer »

af0815 hat geschrieben:Wenn du Probleme bei den Rundungen und den Ungenauigkeiten bei Floattypen bekommst, warum arbeitest du intern nicht mit Integer Datentypen und multipilierst bzw. dividierst ganz einfach mit 1.000.000. Dann bist du auf 6 Stellen genau. Bei Currency wird ja was ähnliches verwendet.

Longint -2147483648 .. 2147483647
Longword 0..4294967295 4
Int64 -9223372036854775808 .. 9223372036854775807

Siehe http://wiki.lazarus.freepascal.org/Vari ... Data_Types
DAS sieht nach der Lösung aus, die ich gesucht habe. Ich bin gerade dabei, das einzubauen und dann auszuprobieren.

Schon mal vielen Dank.
Gruss
GU_Meyer

GU_Meyer
Beiträge: 66
Registriert: Mo 21. Apr 2014, 10:22

Re: Float-/Realzahl auf Anzahl Nachkommastellen kürzen

Beitrag von GU_Meyer »

wp_xyz hat geschrieben:
GU_Meyer hat geschrieben:Leider macht mir Lazarus bei der Eingabe daraus dann 48.295529999999999 .
Das liegt in der Natur des Binärsystems: in der Mathematik liegen reelle Zahlen beliebig dicht, nicht aber im Binärsystem, da man, je nach Datentyp, nur eine begrenzte Anzahl von Bits zur Verfügung hat. Du kannst die Zahlenwerten runden wie du willst, auf 48.29553 wirst du nie exakt kommen, sonst hätte es dir Lazarus schon so angezeigt.
Das habe ich schon verstanden.
wp_xyz hat geschrieben: Nochmals: Du verwechselst die interne Zahlendarstellung als Double oder Extended mit 8 oder 10 bytes mit der Stringdarstellung. Mit den oben genannten Stringformatierungsfunktionen kannst du deine Zahl 48.295529999999999 problemlos in den String '48.29553' verwandeln, was in Karten, Listen, Tabellen etc vernünftig aussieht. Aber bitte: nie den gerundeten String in die Zahl zurück verwandeln und damit weiterrechnen, nimm die Originalzahl.
Ich will meine Zahlen gar nicht als solche ausgeben. Die Koordinaten (Real-Zahlen) werden von mir in Pixel-Werte umgerechnet um damit dann auf einer PNG-Karte ein Shape anzuzeigen.

Trotzdem danke für die Erklärung.
Gruss
GU_Meyer

GU_Meyer
Beiträge: 66
Registriert: Mo 21. Apr 2014, 10:22

Re: Float-/Realzahl auf Anzahl Nachkommastellen kürzen

Beitrag von GU_Meyer »

mschnell hat geschrieben:
GU_Meyer hat geschrieben:Gibt es eine Function/Procedure, die mir eine gegebene Real-Zahl auf eine angegebene Anzahl Nachkommastellen "kürzt" oder auch gern rundet?
Das geht technisch nicht. Real-Zahlen rechnen mit binären Nachkomma-Stellen, nicht mit dezimalen. Die Zahl 0.1 ist als Real (oder Extended) gar nicht exakt darstellbar.

Wenn Du mit einer festen Nackkomma-Stellen-Zahl rechnen willst, nimmst Du am besten Integer (oder Longint, wenn nötig) und skalierst mit einem festen 10^n, denkst Dir das Komma also an einer bestimmten Stelle.

-Michael
Danke, da bin ich gerade dabei...das scheint die für mich praktikable Lösung zu sein.
Gruss
GU_Meyer

GU_Meyer
Beiträge: 66
Registriert: Mo 21. Apr 2014, 10:22

(Gelöst) Re: Float-/Realzahl auf Anzahl Nachkommastellen kür

Beitrag von GU_Meyer »

So, die Beschäftigung mit den vorschlagenen Lösungen hat mir gezeigt, dass das Problem überhaupt nicht die Realzahlen sind - diese stimmen und liefern nach den Berechnungen auch stimmige Werte.
Der Fehler, den ich suche, liegt ganz woanders - und ist damit nicht mehr Thema hier. Wahrscheinlich werde ich das Problem demnächst noch im passenden Unterforum beschreiben und um Hilfe bitten :wink:
Trotzdem vielen Dank an alle, die sich damit für mich beschäftigt und mir helfen wollten.

Gruss
GU_Meyer

Antworten