brauche den Rat eines „Mathe/Java“ Profis. Angeblich lassen sich mit Float und Double keine Dezimalzahlen „exakt“ darstellen. Hintergrund ist, ich möchte mit Währungen/Geld arbeiten, das ja nach dem Dezimalsystem funktioniert.
Angeblich wird in Java ein Float Wert 9.48f intern nicht als 9.48Float gespeichert sondern als 9.47999954… da es für 9.48 keine exakte „binäre“ Darstellung gibt!?
ich wundere mich jetzt wieso das so ist. ES muss doch eine exakte Umrechnung zwischen dem Dezimalen und Binären Zahlensystem möglich sein. Denn ich kann doch Binär oder Dezimal jeder Zahl darstellen. (Insbesondere das Binäre System ist doch eigentlich genauer 2^x als beim Zehner 10^x !? Liegt das daran, dass es rationale Zahlen sind und das nun nicht mehr 2^x berechnet wird, sondern irgendwie anders. Kann man dann nicht einfach den Punkt/Komma verschieben!?
Kann mir jemand Hintergrund Infos liefern (sehr gerne LInks) wo das Thema ausführlich erklärt wird… und das auch veranschaulicht wird, was hier das Problem ist. ODer ist das ein „Problem“ von Java?
Hallo Julian
Es gibt wie Du schon erkennt hast verschiedene Zahlentypen. Das Grundproblem liegt bei deren Berechnung. Zahlen von Double werden mit der Doppelten genauigkeit gerechnet, als Zahlen von anderen Typen. Deshalb definiere deine Variablen als Double Variablen, für genaue berechnungen. Es werden dann meines wissens etwa 15 Stellen nach dem Komma berechnet.
Ein weiteres Problem ist aber dann der Vergleich zwischen einer Ganzzahl oder einer unpräzisen berechneten Zahl und einer reellen Zahl.
Zeigt ein Ganzzahl z.B. 3 an, so ist die reelle Zahl 2,9999999 ungleich drei, wird aber als drei heraus gegeben. Das ist der Grund. Rechne ich mit 2,4,8 oder 16 Kommastellen, dass ist hier die Frage.
Das ganze kann man umgehen mit dem befehl runden auf die Nachkommastelle.
Round(Ausdruck [,AnzahlAnDezimalpunktn])
der Raound Befehl kommt jetzt aber nicht mehr vom Java Script, sondern von dem VB Script.^
Gruss
Sebastian
[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]
brauche den Rat eines „Mathe/Java“ Profis. Angeblich lassen
sich mit Float und Double keine Dezimalzahlen „exakt“
darstellen. Hintergrund ist, ich möchte mit Währungen/Geld
arbeiten, das ja nach dem Dezimalsystem funktioniert.
Angeblich wird in Java ein Float Wert 9.48f intern nicht als
9.48Float gespeichert sondern als 9.47999954… da es für
9.48 keine exakte „binäre“ Darstellung gibt!?
ich wundere mich jetzt wieso das so ist. ES muss doch eine
exakte Umrechnung zwischen dem Dezimalen und Binären
Zahlensystem möglich sein. Denn ich kann doch Binär oder
Dezimal jeder Zahl darstellen. (Insbesondere das Binäre System
ist doch eigentlich genauer 2^x als beim Zehner 10^x !? Liegt
das daran, dass es rationale Zahlen sind und das nun nicht
mehr 2^x berechnet wird, sondern irgendwie anders. Kann man
dann nicht einfach den Punkt/Komma verschieben!?
Rein numerisch gesehen ist ein Rechner mit seiner internen Mantisse und damit der Zahlendarstellung auch irgendwann am Ende.
Kann mir jemand Hintergrund Infos liefern (sehr gerne LInks)
wo das Thema ausführlich erklärt wird… und das auch
veranschaulicht wird, was hier das Problem ist. ODer ist das
ein „Problem“ von Java?
Nein, das kann in anderen Sprachen genauso passieren…
1.10011001100110011001100110011001100… *2^(-4)
(der Exponent wird natürlich auch binär gespeichert)
da der Speicherplatz begrenzt ist, wird aber nicht die ganze binäre Ziffernfolge (die ist unendlich lang) gespeichert sondern nur 24 relevante Stellen (Float, bei Double sind es 53)
damit wird also folgendes gespeichert:
1.10011001100110011001100 * 2(-4)
rechnest du das aber in eine Dezimalzahl zurück, so erhältst du nicht mehr 0,1 sondern 0,0999999940395355.
Das Problem ist also, dass der Dezimalbruch bei der Umrechnung in einen Binärbruch häufig eine Ziffernfolge ergibt, die zu lang für das Speicherformat ist und damit abgeschnitten werden muss.
Hallo Julian,
Hier also noch ne antwort zu deiner frage.
Die nachkommastellen werden in einem dualen system nicht in zehntel,
hundertstel, tausendstel, … dargestellt, sondern in halben,
vierteln, achteln,… .
In der umrechnung von einem zahlensystem in das andere ergeben sich
deshalb ratiaonale brüche, die teilweise unendlich labg sein können
(mit und ohne periode). Das problem tritt prinzipiell bei jedem
digitalen rechner auf, da alle im dualsystem arbeiten. Die interne
stellengenauigkeit wird deshalb größer gewählt als die angezeigten
stellen.
Gruß
Peter
[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]
vielen Dank. Hat mich sehr weitergebracht, und mit den entsprechenden Stichworten habe ich nun dazu auch bei Wikipedia einiges gefunden und so langsam wird mir die Sache klar. Wundere mich nur gerade, dass ich „erst“ jetzt über das Thema stolpere:wink:
pragmatischer ansatz für problem mit währungen: speichere einfach nicht die euro sondern die cent. dann reicht ein einfacher integer bzw. bei grösseren beträgen ein long (ausser du willst die staatsverschuldung abspeichern). für die ausgabe kannst du den betrag nach wunsch wieder durch 100 dividieren - sinnvoller ist es aber, den dezimaltrenner einfach mit string-funktionen einzufügen (du musst die zahl sowieso für die ausgabe in einen string umwandeln - auch wenn dass implizit passiert). das ganze geht jetzt etwas an deiner eigentlichen frage vorbei, löst aber das grundproblem. auf jeden fall wirst du mit dieser lösung nie wieder rundungsprobleme haben (ausser natürlich bei divisionen…).