Seite 1 von 2

(Gelöst) Sichere Fließkommazahl?

Verfasst: 29.05.2009 21:31
von Rebon
Hallo,
Es wäre nett, wenn mir jemand schreiben könnte ob diese Verfahrensweise mit Fließkommazahlen sicher,
bzw. so sicher wie möglich ist,
da ich dieses Programm für eine Shop-Webseite schreibe
und diese Fließkommazahl ein Geldbetrag ist.


- Mit Left() und Len() ignoriere ich die letzte Stelle(immer 0) z.B.12,280 = 12,28 oder 421,420 = 421,42
- ReplaceString ersetzt das Komma durch einen Punkt
- Mit ValD wandle ich den String, den ich aus Liste() erhalte in einen Zahlenwert
- Multipliziere den Wert mit 100 und "übergebe" ihn an die Variable Einzelpreis.d

Code: Alles auswählen

Einzelpreis.d = ValD(ReplaceString(Left(Liste(), Len(Liste())-1), ",", ".")) * 100
- Multipliziere Einzelpreis.d mit Stueckzahl(Integer-Variable) z.B. 7 oder 111

Code: Alles auswählen

Einzelpreis.d * Stueckzahl
- Als letztes teile ich den Wert Einzelpreis.d durch 100 und übertrage den Double-Wert mit 2 Stellen nach dem Komma auf den String Gesamtpreis$

Code: Alles auswählen

Gesamtpreis$ = StrD(Einzelpreis.d / 100, 2)

Verfasst: 29.05.2009 21:59
von sibru
ja, soweit ok... nur Long anstatt Double, das war´s:

Code: Alles auswählen

Einzelpreis.l = Val(ReplaceString(Left(Liste(), Len(Liste())-1), ",", ".")) * 100

Einzelpreis * Stueckzahl

Gesamtpreis$ = StrD(Einzelpreis / 100, 2) 
(bei Double werden ja auch NachKommaStellen mitberechnet, hast also
nur das Komma um 2 Stellen verbogen. Bei Long gibt´s keine NKS´s...)

Gruss SiBru

Verfasst: 29.05.2009 22:04
von Rebon
Danke dir Sibru! :allright:

Verfasst: 29.05.2009 22:32
von Rebon
@Sibru

Du meintest sicher ValD oder?:

Code: Alles auswählen

Einzelpreis.l = ValD(ReplaceString(Left(Liste(), Len(Liste())-1), ",", ".")) * 100
Trotzdem, deine Antwort war sehr informativ! :)

Verfasst: 29.05.2009 22:33
von Kaeru Gaman
Jede Fließkommazahl hat eine begrenzte Genauigkeit.
bei Double ist sie wesentlich geringer, aber auch vorhanden.

für Währungsbeträge würde ich eher dazu raten, mit Integer zu arbeiten, also mit Quad, und stattdessen mit 1/10 cent zu rechnen.

für normale Kassenfunktionen kann auch mal ganze Cent genügen,
allerdings weiß ich nicht, wie präzise die Mehrwertsteuer ausgewiesen werden muss,
mit 1/10 Cent solltest du allerdings auf der sicheren Seite sein.

Für Zinsgeschäfte wären 1/100 Cent besser, auch da kenne ich die Vorschriften nicht.

Aber ganz grundsätzlich ist eine Integer immer genau, bis sie oben anstößt.
eine Float stößt nie oben an, dafür wird sie immer ungenauer.

kleine Demo:

Code: Alles auswählen

VInt.l = Pow( 2, 24 ) -5
CInt.l = 1

VFlo.f = VInt
CFlo.f = 1

For n=0 To 9
  VInt + CInt
  Debug "Integer: " + Str( VInt )
  VFlo + CFlo
  Debug "Float: " + StrF( VFlo )
Next
bis 2^24-1 funktioniert dir Float auf 1.0 genau, darüber nicht mehr, die Addition wird nicht mehr korrekt ausgeführt.
das liegt daran, dass bei einer 32bit Float 23bit für die Mantisse verwendet werden.

Verfasst: 29.05.2009 22:48
von Rebon
Auch danke an dich Kaeru! :allright:
Zwar hab ich keine Ahnung, was z.B. Pow
bedeutet, aber ich werds herausfinden (PB-Help).

Verfasst: 29.05.2009 22:58
von Kaeru Gaman
das erzeugt nur 2^24...

statt Pow( 2, 24) -5 hätte ich auch 16777211 schreiben können...

Verfasst: 29.05.2009 23:10
von Rebon
Also, wenn ich deine Demo richtig verstanden habe,
dann geht die Genauigkeit bei Float bis 16777216.000000.

Verfasst: 29.05.2009 23:31
von Kaeru Gaman
die Genauigkeit um 2^0 also 1

wenn du auf 0.01 genau rechnen willst, ist schluss bei 167772.11
wenn du auf 0.001 genau rechnen willst, ist schluss bei 1677.7211

wie gesagt, Double ist zwar wesentlich genauer, aber auch dort greift irgendwann die ungenauigkeit.

deswegen benutze lieber Quads und rechne mit 1/10 Cent,
dann sind alle Beträge bis zur Summe ±9.223.372.036.854.775,807 € wirklich genau.

PS:
bei einer Integer bekommst du einen klaren Überlauf, das merkt man ganz deutlich.

bei Fließkomma bekommt man auch weiterhin richtig aussehende Zahlen zurück,
sie stimmen nur nicht mehr, wie du an der Demo gut sehen kannst.

Verfasst: 29.05.2009 23:38
von Rebon
Kaeru Gaman hat geschrieben: deswegen benutze lieber Quads und rechne mit 1/10 Cent,
dann sind alle Beträge bis zur Summe ±9.223.372.036.854.775,807 € wirklich genau.
Ich werd's versuchen, muß mich aber erst noch genauer
über Quads informieren.
Da ich im meinem Programm, später noch die Mehrwertsteuer
ausrechnen muß, ist deine Hilfe sehr nützlich!
Danke nochmal! :allright:

Edit: Ich hab mich in der Help von PB verlesen, muß mich nicht über Quads informieren. :mrgreen:
Hab da was mit BinQ bzw. dem Binärformat gelesen.