Falsche Berechnung meines Java-Rechners
lima-city → Forum → Programmiersprachen → Java
antworten
beispiel
code
dank
double
ergebnis
fehler
http
meinung
problem
rechnung
sagen
standard
system
taschenrechner
treten
typ
url
verhindern
zahl
-
ho ;)
Ich habe nun angefangen, mich mit GUI Programmierung (Swing) mit Java zu beschäftigen.
Die erste Aufgabe, dich ich hatte, war einen kleinen Basis-Taschenrechner zu erstellen. Soweit so gut, und nicht wirklich schwierig. Jetzt bin ich fertig, und mein Taschenrechner verrechnet sich minimal bei manchen Gleitkommazahlen-Eingaben :(
Um ein konkretes Beispiel zu nennen:
Ich gebe 3.3-2.2 ein, und bekomme als Ergebnis 1.0999999999999996 statt 1.1
Meine Frage lautet nun: Ist das unter Java üblich? Wie kann ich das verhindern?
Ich bin mir außerdem sicher, dass es nichts mit der GUI zu tun hat. Dafür habe ich extra einen Unit-Test gemacht, und das Ergebnis war wie erwartet:
java.lang.AssertionError: expected:<1.1> but was:<1.0999999999999996>
Falls jemand den Code sehen will, schreibt mir bitte eine PM mit eurer E-Mail Adresse. Ich schicke euch das Eclipse Projekt dann per Mail. (Ich poste ihn hier absichtlich nicht, da das ein totaler Overhead wäre. Außerdem bin ich mir sicher, in der Zeile "neuerWert = ersteZahl - zweiteZahl;" keinen Fehler gemacht zu haben xD )
Thx im voraus für die Antworten
Sincer -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage
-
was für datentypen besitzen deine variablen?
-
Sry, das habe ich vergessen zu sagen...
Alle Zahlen sind vom Typ double.
// EDIT:
Aber versteht mich nicht falsch, er verrechnet sich wirklich nur bei manchen Situationen...
3.3+2.2 = 5.5 -> ok.
2.2-1.1 = 1.1 -> ok.
Meiner Meinung nach total eigenartig.
lg
Sincer
Beitrag zuletzt geändert: 2.3.2011 19:21:37 von sincer -
wenn dus so machst
short a = (short)3.3; short b = (short)2.2; a-b >> 1 (int)
oder:
long g = (long) 3.3; long h= (long) 2.3; g-h >>1 (long)
du solltest dir eventuell klarmachen mit welchem system die datentypen int,long,float,double rechnerintern dargestellt werden
da ist es kein wunder das bei 1 - 0.1 - 0.1 - 0.1 - 0.1 - 0.1 - 0.1 - 0.1 nicht 0.3 sondern 0.30000000000000016 rauskommt, mal so als beispiel
Beitrag zuletzt geändert: 2.3.2011 19:21:56 von mordred -
mordred schrieb:
du solltest dir eventuell klarmachen mit welchem system die datentypen int,long,float,double rechnerintern dargestellt werden
da ist es kein wunder das bei 1 - 0.1 - 0.1 - 0.1 - 0.1 - 0.1 - 0.1 - 0.1 nicht 0.3 sondern 0.30000000000000016 rauskommt, mal so als beispiel
Du hast recht, was dein letztes Beispiel angeht... Genau das kommt bei mir raus...
Aber ich verstehe nun noch immer nicht warum.
Ich habe nun alle Rechnungen nach double gecasted...
result = (double) (number1 - number2);
Aber das hat nichts verändert (ist meiner Meinung nach auch unnötig, da sowieso beide Zahlen (number1 und number2) vom Typ double sind), und ich glaube auch, dass du das gar nicht gemeint hast.
Würdest du mir noch erklären, warum dieser Fehler logisch ist?
Und vor allem: Wie kann ich das verhindern?
Danke
Sincer
// EDIT:
Komisch, und wenn ich 0.7 eintippe, sehe ich am Display 0.7000000000000001. Check ich nicht...
Und wenn ich dann weiter eingebe... 6543 korrigiert sich die Zahl auf einmal wieder nach 0.76543. *am Kopf kratz* ^^
Beitrag zuletzt geändert: 2.3.2011 19:33:47 von sincer -
Hallo sincer,
ein double in Java entspricht dem Standard IEEE 754. In diesem Format können einige Zahlen, welche in dezimaler Schreibweise kein Problem sind, nur als unendliche Reihe dargestellt werde. Da ein Double aber nur 64 Bit hat und nicht unendlich viele, wird irgendwo abgeschnitten und man bekommt die Rundungsfehler.
Genaueres dazu kannst Du zum Beispiel hier nachlesen:
http://de.wikipedia.org/wiki/IEEE_754
Und hier ist noch was zum Spielen:
http://www.h-schmidt.net/FloatApplet/IEEE754de.html
Beitrag zuletzt geändert: 2.3.2011 19:49:36 von darkpandemic -
darkpandemic schrieb:
ein double in Java entspricht dem Standard IEEE 754.
That's new to me :D
Sehr interessant. (Weißt du zufällig, ob das bei C / C++ auch so ist?)
Ok, jetzt weiß ich warum das passiert. (Bei der Umrechnung von double zwischen Dual und Dezimal...)
Kannst du mir noch sagen, wie ich das verhindere? Oder habe ich da gar keine Chance?
Thx auf jeden Fall :)
Sincer -
Hallo sincer,
ich kann Dir jetzt leider nicht sagen, ob im C oder C++ Standard IEEE 754 festgeschrieben ist. Aber solange Du auf normaler PC-Hardware programmierst wirst Du die selben Ergebnisse bekommen, da die Rechner intern gemäß IEEE 754 arbeiten und C/C++ das direkt verwendent (außer wenn Intel mal wieder einen Bug in der FPU hat ).
Vermeiden kann man so etwas in Java durch die Verwendung von BigDecimal.
Da kannst Du die gewünschte Genauigkeit vorgeben und die wird dann auch eingehalten. Allerdings sind die Rechnungen dann um einiges langsamer. -
BigDecimal vermeidet das Problem nicht, sondern es verändert das Problem so, dass das Problem sich so verhält, wie du es vom Decimalsystem her kennst.
Beispiel
Bei BigDecimal wirst du auch gezwungen sein, zu runden! Und zwar bei dieser Rechnung: 1 / 3 = ein Drittel, aber das hätte dich vermutlich nicht gestört / gewundert.
Bei Double / double / float , tritt prinzipiell das gleiche Problem auf, weil es jedoch in einem anderen Zahlensystem (dem binären) speichert, passiert dies bei anderen Zahlen:
0,25 -> kein Problem,
0,2 -> Problem, weil es im Binärsystem eine Periode ist. -
ho ;)
Ja, du hast recht, das habe ich dann auch bemerkt.
Ich habe mein Problem nun mit BigDecimal und Runden gelöst.
Danke an alle für die Antworten :)
Sincer -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage