Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   FloatToStrF Rundungsfehler ? (https://www.delphipraxis.net/206772-floattostrf-rundungsfehler.html)

egentur 28. Jan 2021 08:09

FloatToStrF Rundungsfehler ?
 
Hallo zusammen

Habe hier eine wahrscheinlich simple Frage.

In einer Software (Delphi 6) habe ich ein Problem mit der Funktion

Var
RV : Double;
Result :String;
begin
Result := FloatToStrF(RV,ffFixed,6,4);
end;

RV ist 0.50015
Beim ersten Aufruf ist Result korrekt 0.5002

Das bleibt auch so, bis ich den Wert mal mit QuickReport ausdrucke.

Danach ergibt der gleiche Aufruf der Funktion

RV immer noch 0.50015
Result = 0.5001

Wenn RV vom Typ Single ist, dann bleibt Result korrekt 0.5002

Hat hier FloatToStrF ein Problem mit dem übergebenen ParameterTyp ?

Danke für jeden Hinweis !

egentur 28. Jan 2021 11:51

AW: FloatToStrF Rundungsfehler ?
 
Nachtrag

Im Debugger sind die Parameter für die Funktion FloatToStrF korrekt.

Ich habe nur den Eindruck das die Funktion einmal rundet und dann (nur nach einem Ausdruck) einfach ein truncate macht!

Der schöne Günther 28. Jan 2021 12:23

AW: FloatToStrF Rundungsfehler ?
 
Ist das wieder der Mythos mit den Druckertreibern welche die FPU-Einstellungen verdrehen?
Macht es einen Unterschied wenn man es an einen PDF-Drucker sendet?

egentur 28. Jan 2021 12:36

AW: FloatToStrF Rundungsfehler ?
 
Hallo

Leider macht es keinen Unterschied welchen Druck man benutzt.
Im Prwview vom Fastreport kann ich auch nach PDF exportieren ( kein Problem ),
nur wenn ich drucke reagiert die Funktion nachher anders.

Das löst sich nur auf , wenn ich die Applikation ganz schließe !

Rollo62 28. Jan 2021 16:01

AW: FloatToStrF Rundungsfehler ?
 
Ich bin ja nicht 100% sicher, aber FloatToStrF würde ich nicht fürs Runden missbrauchen.
Insbesondere wenn es mir wirklich auf die letzte Stelle ankommt.
Das steuert doch nur die Anzeige, und die Rundungsfunktion ist Abfallprodukt.
Evtl. vorher Runden, wie gewünscht mit der gewünschten Rundungs-Funktion, und dann erst FloatToStrF.

Incocnito 28. Jan 2021 16:29

AW: FloatToStrF Rundungsfehler ?
 
Ja scheint auf den ersten Blick seltsam ...

0.5025 beispielsweise wird bei IEEE-754 (das müsste Single sein)
als
0.502499997615814208984375
gespeichert (dichter kommt der PC mit der Speicherung in 32-Bit nicht ran)
Dort würde ein Runden auf 3 Nachkommastellen nicht wie erwartet
0.503 sondern 0.502 ergeben.

Runden war schon immer ein Spaß für sich.

Dein 0.5015 wäre in IEEE-754 (Single?) übrigens 0.50150001049041748046875.
Es hilft also nur bei genau dieser Zahl von Double auf Single zu wechseln,
bei anderen Zahlen schlägt es genau umgekehrt fehl, bei noch anderen Zahlen
wäre der Datentyp dann vermutlich egal.

Wenn du 4 Nachkommastellen als Maximum hast könnte Currency gehen,
oder du baust deine eigene "sichere" Runden-Funktion.

MfG Incocnito

egentur 29. Jan 2021 15:37

AW: FloatToStrF Rundungsfehler ?
 
Hallo Incocnito

Genauso verhält es sich bei mir.
Ich habe die 8 Jahre alte Software übernommen.

Ein Messwert kommt als String '0.50015' ,
wird dann für eine weitere Berechnung in Double konvertiert

val(messwert, double, error) double ist dabei 0.500149999...

und dann wieder in String
result := Floattostrf(double , fffixed, 6,4)

result ist dann '0,5001'

zur Anzeige.

Warum rundet die Funktion an diese Stelle ab statt auf (0,5002) ?

Ist dies ein bekannter Fehler ?

Delphi.Narium 29. Jan 2021 15:48

AW: FloatToStrF Rundungsfehler ?
 
Weil 0.500149999 bei Rundung auf vier Nachkommastellen halt 0.5001 ergibt.

Floattostrf weiß nicht, dass vorher aus dem String 0.50015 ein Double 0.500149999 gemacht wurde und daraus dann eigentlich ein String 0.50015 werden müsste, der dann zu 'nem gerundeten String 0.5002 werden sollte.

Floattostrf kennt nunmal nur den aus dem String erstellten Doublewert von 0.500149999, rundet den auf vier Nachkommastellen = 0.5001 und macht dann daraus einen String.

himitsu 29. Jan 2021 15:57

AW: FloatToStrF Rundungsfehler ?
 
Warum?
Das wurde doch gesagt und du hast es selbst auch nochmal bestätigt.

Intern wird es als 0.500149999... gespeichert (Darstellungsfehler, da wir in einem 10er-System denken, aber der Computer mit einem 2er-System rechnen muss.
(10 lässt sich nunmal nicht als 1 Bit darstellen und wird somit zwangsläufig unscharf, denn 8-10-16)

Und bei Rundung auf 4 Nachkommastellen, kommt für 0.500149999 nunmal 0.5001 raus.


Wenn man davon ausgehen könnte, dass bei String-zu-Float immer abgerundet würde,
dann könnte man vor dem Runden einen kleinen Offset zurechnen (z.B. 0.00001 also 10% von der kleinstmöglichen Nachkommastelle) und schon stimmt es.
Aber ich vermute fasst hier wird das Nächstliegendste gespeichert.
Würde dabei manchmal aufgerundet, also 0.500150000001..., dann müsste man den Offset ja eigentlich abziehen.



Aus diesem Grund gibt es z.B. auch den Typ Currency (ist intern ein Int64, wo die letzten 4 Dezimalstellen als Nachkomma definiert sind, womit es dort nicht solche Rundungsfehler gibt, bei bis zu 4 Nachkommastellen)
Man kann auch BCD oder andere Big-Nummer-Systeme verwenden, wenn es sein muß. (BCD speichert in einem 10er-System und hat somit keinen Darstellngsfehler)

Incocnito 29. Jan 2021 16:09

AW: FloatToStrF Rundungsfehler ?
 
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

Andreas13 29. Jan 2021 16:26

AW: FloatToStrF Rundungsfehler ?
 
Zitat:

Zitat von himitsu (Beitrag 1481782)
... Aus diesem Grund gibt es z.B. auch den Typ Currency (ist intern ein Int64, wo die letzten 4 Dezimalstellen als Nachkomma definiert sind, womit es dort nicht solche Rundungsfehler gibt, bei bis zu 4 Nachkommastellen)

Aber nur, wenn man lediglich addiert oder subtrahiert. Bei sonstigen mathematischen Operationen gibt es auch dort Rundungsfehler.
Andreas

himitsu 29. Jan 2021 18:02

AW: FloatToStrF Rundungsfehler ?
 
In x86 war eine Erweiterung für BCD integriert,
aber im 64 Bit hat es nicht mehr eingebaut und sich den Platz im Silizium gespart.
https://en.wikipedia.org/wiki/Intel_BCD_opcode

Schade, dass es praktisch niemand benutzt hatte und man es somit als Nutzlos ansah. :cry:

egentur 1. Feb 2021 13:48

AW: FloatToStrF Rundungsfehler ?
 
Danke für die vielen Hinweise!

Meine Situation ist folgende:
Ich habe eine Messgerät das den Wert immer mit 5 Nachkommastellen als String liefert. z.B. '0,50015'

Dieser wert wir dann für eine Nebenrechnung mit val() in eine Double Variable konvertiert.


Der User kann dann in der Applikation einstellen, ob er den Wert mit 5 oder weniger Nachkommastellen sehen will.

Mein Problem war eben, wenn er 4 Nachkommastellen einstellt,
wird aus der Double Var mit Floattostrf(var, fffixed,6,4) einmal 0,5002 und einmal 0,5001.

Welche Bedingung bringt Floattostrf dazu an der gleichen Codestelle zwei verschiedene Ergebnisse zu liefern ?

Incocnito 2. Feb 2021 11:01

AW: FloatToStrF Rundungsfehler ?
 
Das Problem hast du mit anderen Zahlen auch bei 2 oder 3 Nachkommastellen.
Ist dir vielleicht nur noch nicht aufgefallen.
Einzig bei 1 Nachkommastelle hättest du das Problem nicht, da es da nur X,5 gibt,
welches in Double (und Float und Extended und whatever) unproblematisch ist.

Du brauchst halt eine generelle Lösung für das Problem und da hilft es dir nur
zu verstehen, warum das passiert. Was du am Ende im Quelltext schreiben musst,
kann dir so vermutlich keiner sagen.

Erst-Bester-Versuch: Addiere ein kleines Diff auf die Zahl drauf.
Wenn du als String immer 5 Nachkommastellen bekommst, dann rechne 1 auf die sechste Nachkommastelle.
z.B. 0,50015 + 0,000001 = 0,500151 ... wenn der Computer
0,500149999999999 davon macht würde er mit 0,50015099999999 arbeiten ...
wenn man den Wert rundet (durch die Anzeige) dann kommt das "richtige" bei rum.
Auch für das Abrunden wäre das unproblematisch, da dir der String ja immer 5 Nachkommastellen liefert.
auch bei 0,50014 wird 0,500141 daraus, welches genauso abgerundet wird wie der "echte" Wert.

[Edit:] Aso, um deine Frage zu beantworten. Alleine durch lustiges Konvertieren oder umspeichern

Delphi-Quellcode:
DerWert := StrToFloatDef(WertAusSensor(), 0); // <- Hier kommt "0,50015"
ShowMessage(FloatToStrF(DerWert, ffFixed, 6, 4));
... ist schon was anderes als ...

Delphi-Quellcode:
ShowMessage(FloatToStr(0.50015, ffFixed, 6, 4));

Liebe Grüße
Incocnito

markus888 2. Feb 2021 19:53

AW: FloatToStrF Rundungsfehler ?
 
Zitat:

Zitat von Incocnito (Beitrag 1481784)
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.

Incocnito 3. Feb 2021 08:47

AW: FloatToStrF Rundungsfehler ?
 
Zitat:

Zitat von markus888 (Beitrag 1482063)
Zitat:

Zitat von Incocnito (Beitrag 1481784)
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.


Zitat:

Zitat von markus888 (Beitrag 1482063)
...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

Andreas13 3. Feb 2021 22:31

AW: FloatToStrF Rundungsfehler ?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von egentur (Beitrag 1481932)
... Meine Situation ist folgende: Ich habe eine Messgerät das den Wert immer mit 5 Nachkommastellen als String liefert. z.B. '0,50015'
Dieser wert wir dann für eine Nebenrechnung mit val() in eine Double Variable konvertiert.
Der User kann dann in der Applikation einstellen, ob er den Wert mit 5 oder weniger Nachkommastellen sehen will.
Mein Problem war eben, wenn er 4 Nachkommastellen einstellt,
wird aus der Double Var mit Floattostrf(var, fffixed,6,4) einmal 0,5002 und einmal 0,5001.
Welche Bedingung bringt Floattostrf dazu an der gleichen Codestelle zwei verschiedene Ergebnisse zu liefern ?

Hallo Egentur,
ich kann Dein ursprüngliches Problem nicht reproduzieren: Bei mir (XE5 Pro) funktioniert FloatToStrF (..) korrekt. Vielleicht ist noch ein Bug in XE2? Daher habe ich für Dich einige Routinen für die manuelle Rundung als Ersatz von FloatToStrF(..) im beiliegenden Testprogramm zusammengestellt.
Gruß, Andreas

bcvs 4. Feb 2021 07:05

AW: FloatToStrF Rundungsfehler ?
 
Das Problem war ja nicht FloatToStrF, sondern die Tatsache, dass 0.50015 in einem double zu 0.50014999999 wird und dann auf 4 Stellen gerundet 0.5001. Die Funktion, mit der gerundet wird, spielt dabei keine Rolle,

Ändere mal in deinem Beispiel den Typ von "Zahl" zu double. Dann sieht man das schön.

egentur 4. Feb 2021 11:09

AW: FloatToStrF Rundungsfehler ?
 
Hallo bvcs

Mein Problem war schon floattostrf

Selbst wenn ich den Wert der Double Variablen explizit auf 0.500149999999999983 setze ( was ja dann bei floattostrf(var,fffixed,6,4) 0.5001 ergeben müsste

habe ich bei den Aufrufen immer das Ergebnis 0.5002

Erst nach einem Ausdruck egibt es dann 0.5001 und bleibt auch so, bis zu einem erneuten Prgogrammstart.

Welche Randbedingungen ( Luftdruck, Zimmertemperatur ) führen denn dazu, das floattostrf bei zwei identischen ( an gleicher Stelle) Aufrufen
eine unterschiedliches Ergebnis liefert ?

Moombas 4. Feb 2021 11:38

AW: FloatToStrF Rundungsfehler ?
 
Kann das Problem also im Quickreport sein und nicht in der Funktion?
Darüber schon mal nachgedacht/geforscht?

Incocnito 4. Feb 2021 15:35

AW: FloatToStrF Rundungsfehler ?
 
Klingt als würde da ein Modul eine globale Einstellung ändern ...
TFormatSettings oder sowas.

Hilft denn mein Tipp nicht, um zuverlässig immer das gleiche Ergebnis zu erhalten?

LG Incocnito

egentur 4. Feb 2021 16:00

AW: FloatToStrF Rundungsfehler ?
 
Hallo Incocnito

Doch , danke

Ich werde da die Messwerte immer als string mit 5 Nachkommastellen geliefert werden
nach der Konvertierung in double 0.000001 addieren
dann futionierts auch mit floattostrf(x,fffixed,6,4)

Ich musste das so machen weil der User die Nachkommastellen in seinem Grid/Report individuell einstellen wollte.


aber denoch würde ich gerne den Grund wissen !!

Incocnito 5. Feb 2021 09:02

AW: FloatToStrF Rundungsfehler ?
 
Vielleicht wurde in der Routine auch an dem CPU FloatingPoint ControlWord herumgefummelt.

vgl.
https://www.intel.com/content/dam/ww...l-1-manual.pdf
8.1.5 x87 FPU Control Word

Obwohl mir die Auswirkungen jetzt nicht bekannt sind.
Auf dem ersten Blick scheint es nur bei SSE- und SSE2-CPU-Funktionen relevant zu sein.
Fraglich, ob die an der Stelle überhaubt benutzt werden.

Du könntest zum Testen das ControlWord jeweils vorher auslesen.
(System.Get8087CW()) und prüfen ob irgendwelche Aufrufe vom QuickReport
da etwas ändern. Wir mussten feststellen, dass beim Arbeiten mit der Apollo-Datenbank
eine Funktion da was verstellt.

Ich hoffe diese Information hilft weiter.

Liebe Grüße
Incocnito

egentur 5. Feb 2021 11:33

AW: FloatToStrF Rundungsfehler ?
 
Hallo Incocnito

In der Tat.

Beim ersten Durchlauf ergibt System.Get8087CW()

den Wert 4722 und bleibt bestehen ( hier rundet floattostrf(rv,fffixed,6,4) den Double Wert von 0.500149999999999983 auf 0,5002)

bis ich aus dem PrintPreview den Ausdruck auf den Drucker (unabhängig vom Druckertyp) wähle

danach ergibt System.Get8087CW()
den Wert 4978 und von da an wird korrekt gerundet also ( floattostrf(rv,fffixed,6,4) den Double Wert von 0.500149999999999983 auf 0,5001)

Gibt es dann hier eine Lösung ausser deiner beschriebenen ?

Achim Kalwa 5. Feb 2021 13:41

AW: FloatToStrF Rundungsfehler ?
 
Zitat:

Zitat von egentur (Beitrag 1482337)
Beim ersten Durchlauf ergibt System.Get8087CW() den Wert 4722 [...]
bis ich aus dem PrintPreview den Ausdruck auf den Drucker (unabhängig vom Druckertyp) wähle
danach ergibt System.Get8087CW()

Auf genau diese Problematik hatte doch Der schöne Günther in Beitrag #3 schon hingewiesen:
Zitat:

Ist das wieder der Mythos mit den Druckertreibern welche die FPU-Einstellungen verdrehen?
Scheint also doch kein Mythos zu sein... Oder doch ein Problem von QuockReport?

Delphi.Narium 5. Feb 2021 13:52

AW: FloatToStrF Rundungsfehler ?
 
http://docwiki.embarcadero.com/Libra...stem.Set8087CW

http://docwiki.embarcadero.com/CodeE...087CW_(Delphi)

Demnach müsste 4978 der Defaultwert sein und die 4722 die Folge irgendeiner Änderung. Keine Ahnung wie man herausbekommt, woraus sie resultiert.

Eventuell mal alle Sourcen durchsuchen, ob irgendwo Set8087CW aufgerufen wird und welcher Wert dort gesetzt wird.

Wenn da nix zu finden ist, wird das von "irgendeiner Software / irgendeinem Treiber / ..." verändert.

Fraglich ist hierbei: Welche Nebenwirkungen entstehen, wenn Du selbst per Set8087CW(4972) den Wert setzt. Wer wie was auch immer die 4722 setzt, macht das (vermutlich) aus 'nem betimmten Grund und nicht nur "Just For Fun" :-(

Edit:

Ein "ungünstiger" Aufruf von SetPrecisionMode aus der Unit Math könnte eventuell auch eine unerwünschte Nebenwirkung haben.

Incocnito 5. Feb 2021 14:30

AW: FloatToStrF Rundungsfehler ?
 
Hier
http://docwiki.embarcadero.com/Libra....Default8087CW
steht, dass der Default-Wert $1332 also 4714 sein soll.

Aber auch bei mir ist beim Start dort schon ein anderer Wert enthalten.
Indy? QuickReport? Apollo Datenbank? Jedi? Keine Ahnung, wer den Wert verstellt.

Für deinen Fall:
4722 = 0001 0010 0111 0010
Rounding Contol = 00
Precission Control = 10 = Double Pressision 53bits
---
4978 = 0001 0011 0111 0010
Rounding Contol = 00
Precission Control = 11 = Double Extended Pressision 64bits

Eine höhere Genauigkeit führt hier nur zu einem anderen Ergebnis.
Meiner Meinung nach wird zwar bei erhöhter Genauigkeit mathematisch richtig rundet,
aber bei Einschaltung des gesunden Menschenverstandes eher falsch rundet.
Aufgerundet wird ja immer bei "5", aber durch die "Ungenauigkeit" des
PC steht dort "4,99999999", also muss ich trotzdem aufrunden, eben
weil das ja nur ein falscher Ausgagswert Aufgrund der technischen Gegebenheiten ist.
Außerdem um darauf wieder zurück zu kommen ist das jetzt der Fall für
deine 0,50015 ... für andere Zahlen sieht das wieder anders aus und du kannst
nicht "alle" Möglichkeiten testen (behaupte ich mal).

Das unterschiedliche Verhalten kann also durch das 8087 ControlWord erklärt werden.
Trotzdem empfehle ich (wie du es ja schon gemacht hast) das einfach zu umgehen.

LG Incocnito

egentur 5. Feb 2021 15:04

AW: FloatToStrF Rundungsfehler ?
 
Danke an Incocnito und alle anderen

Ich habe auch im Source keine Stelle gefunden wo das explizit umgestellt wird.

Ich mach dann mal +0.000001

Schöne Grüße :-D

egentur 5. Feb 2021 15:39

AW: FloatToStrF Rundungsfehler ?
 
Kurzer Nachtrag

Ich hab doch noch eine DLL gefunden, die für die serielle Schnittstelle zu einem bestimmten
Messgeräte verwendet wird, und die verstellt den Wert !

Natürlich ohne source von extern :cry:

Aber wenn man endlich weiß :-D


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:53 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz