AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

FloatToStrF Rundungsfehler ?

Ein Thema von egentur · begonnen am 28. Jan 2021 · letzter Beitrag vom 5. Feb 2021
Antwort Antwort
Incocnito

Registriert seit: 28. Nov 2016
230 Beiträge
 
#1

AW: FloatToStrF Rundungsfehler ?

  Alt 29. Jan 2021, 16:09
Ok, Himitsu war schneller ... ich poste das aber trotzdem jetzt!

1) Um Gedanklich ungefähr dahin zu kommen zu verstehen, was da passiert:
Man nehme an, für die Nachkommastellen gäbe es im Computer nur 2 Bits.
Durch die Beschaffenheit eines Computers könnte dieser nur auf 1/4-Werte speichern.
Er kann also nur 0.000, 0.250, 0.500 und 0.750 (und 1.000 usw.) speichern.
Jetzt kommst du mit dem Wert "0.100" und der Computer muss sich entscheiden,
ob er das als 0.000 oder als 0.250 speichern soll.
Der Computer hat herausgefunden, dass 0.000 dichter am Originalwert ist, also
speichert er den Wert als diesen ab.
Wenn du dann fragst "Wert <> 0" sagt der Computer "Nein", obwohl dein Ursprungswert
sehr wohl <> 0 wäre.

Vielleciht hilft auch das hier:
https://www.matheretter.de/rechner/dezimalbinar

2) Der Datentyp Currency hilft hier, da er in Wirklichkeit den 10000-stel Wert
speichert. (4 Nachkommastellen)
Speicherst du 1,20 € als Currency speichert er 12000 als Integer (Int64), weiß aber
wenn du damit arbeiten willst, dass du nur den 10000sten Teil meinst.
Für das Runden von Beträgen, welche in Float-Werten (Real, Float, Double, Extended)
in irgendeiner Form zwischengespeichert wurden habe ich etwas gebaut,
was das kleinste Diff aufaddiert, die Kommastellen (um 2 Stellen) verschiebt
0,5 aufaddiert, dann das ganze Truncated und den Wert wieder zurück verschiebt.
Hierbei klappte das Runden dann bisher immer auch bei Werten aus Fließkommavariablen.
Andere Funktionen hatten immer irgendeine Zahl, bei der das Runden
dann doch nicht funktionierte. Eben wegen der Beschaffenheit der Fließkommazahlen
in der EDV.

Das war schon wieder viel zu viel Text. Sorry.

Liebe Grüße
Incocnito
  Mit Zitat antworten Zitat
markus888

Registriert seit: 23. Dez 2018
46 Beiträge
 
#2

AW: FloatToStrF Rundungsfehler ?

  Alt 2. Feb 2021, 19:53
habe ich etwas gebaut, was das kleinste Diff aufaddiert
darf ich fragen, was du da genau machst?

Beim Konvertieren zu einem String, wird ja vermutlich auch eine Differenz aufaddiert.
Hab mich da aber noch nicht tiefer damit beschäftigt.
  Mit Zitat antworten Zitat
Incocnito

Registriert seit: 28. Nov 2016
230 Beiträge
 
#3

AW: FloatToStrF Rundungsfehler ?

  Alt 3. Feb 2021, 08:47
habe ich etwas gebaut, was das kleinste Diff aufaddiert
darf ich fragen, was du da genau machst?...
Ich ermittel je nach Datentyp die kleinste Differenz, welche beim Aufaddieren den Wert der Variable noch ändert.
Zum Verständnis: Wenn du 4 Bits als Nachkommastellen hättest, könntest der Computer ja
1,00 / 1,0625 / 1,1250 / 1,1875 / 1,2500 / 1,3125 / 1,3750 / 1,4375 / 1,5000 / 1,5625 / 1,6250 / ...
abbilden.
Die Genauigkeit welche ich brauche darf dann natürlich nur entsprechend sein. In dem Fall mit 4 "Nachkomma-Bits"
reicht es nichmal für 1 Nachkommastelle, aber ich kann hier nicht eine Liste für 10 Nachkomma-Bits machen,
damit wir 2 Nachkommastellen zum "Spielen" haben.
Wenn ich '1,4' als Wert bekomme sagt der PC "Ok, 1,3750 ist näher dran als 1,4375, dann speicher ich '1,4' als 1,3750".
Ich rechne in diesem Fall stumpf 0,0625 auf alle ermittelten Ergebnisse.
Wenn ich also den Wert 1,3750 sehe wird daraus 1,4375. Welcher bei der Ausgabe wieder unkritisch wäre.

Ja, wie gesagt, die 4 Bits reichen leider nicht für 1 Nachkommastelle, wie man bei der 1,5000 sieht.
Ich denke mal, dass man 7 Nachkomma-Bits bräuchte (1/128 = 0,0078125) für dieses
Prinzip.
Rechne ich bei 1,5000 die 0,0625 drauf würde gerundet ja tatsächlich 1,6 heraus kommen.
Wenn ich
http://docwiki.embarcadero.com/RADSt...ormate_(Delphi)
richtig lese hat selbst Single 23 Nachkomma-Bits.
Für eine Anwendung die 4 Nachkommastellen braucht ist das also ausreichend.

Anmerkung für die Allwissenden unter euch: Nein, ich lasse die Verschiebung der Mantisse
jetzt mal absichtlich weg und beziehe mich nur auf die Differenz zum Wert 1,0.
Sonst wird das echt zu konpliziert.


...Beim Konvertieren zu einem String, wird ja vermutlich auch eine Differenz aufaddiert.
Hab mich da aber noch nicht tiefer damit beschäftigt.
Der Computer bahandelt hier nur die Darstellung als Text. Das ist nur
numerisch gesehen ein Aufaddieren (oder Abziehen), lass dich davon nicht beirren.

---

Hast du mal versucht auf die Werte, welche du vom Sensor bekommst einfach etwas
drauf zu rechnen? ... Du könntest zum Testen sogar hingehen und sowas machen:
Delphi-Quellcode:
var
  dWert : Single; // oder Double
  sWert : String;
...
  sWert := WertAusSensor();
  dWert := StrToFloatDef(sWert, 0);
  if (dWert <> Trunc(dWert)) then sWert := sWert + '1'; // Nur wenn Nachkommastellen, sonst machst du ja aus "2" eine "21" ;-)
  dWert := StrToFloatDef(sWert, 0);
  ShowMessage(FloatToStrF(dWert, ffFixed, 6, 4));
Ob man jetzt stiltechnisch sagt "ich mache StrToFloat() und fange die Exception ab/nicht ab" oder
ob man für den Default-Wert einen unrealistischen Wert nimmt und eine Meldung ausgibt,
falls dieser Wert dann heraus kommt oder man direkt mit "TryStrToFloat" arbeitet,
kann sich meinetwegen jeder selbst aussuchen.
Für deinen speziellen Fall dürfte das so aber reichen.

Anmerkung: Da es je nach Anwendungsfall anders gehandhabt werden muss, können Programmiersprachen
das nicht "von sich aus korrigieren". Delphi bietet allerdings mit dem Datentyp "Currency" eine
gute Möglichkeit solche Fehler mit Hausmitteln einfach zu bekämpfen, wenn man 4 Nachkommastellen
und weniger braucht. Leider reicht das für deinen Fall hier nicht.

Melde dich, ob du mit meinem Ansatz das Problem beheben konntest.

LG Incocnito
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:52 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz