Warum ergibt 5,0 minus 4,9 nicht 0,1?

SpaceCookie

Neues Mitglied
Moin moin,
ich hab ne Frage:
Warum ergibt das hier:
System.out.println(5.0 - 4.9);
das hier:
0.09999999999999964 ?
Ist ja ganz knapp dran, aber trotzdem falsch. Gibt es dafür ne Erklärung? Warum passiert das? Und: Kann ich das einfach durch Math.round() lösen?
Ich bin Anfänger btw.
Vielen Dank im Voraus!
 
K

kneitzel

Gast
Schauen wir uns nur einmal duale Zahlen an:

Vor dem Komma haben wir die Wertigkeiten 1, 2, 4, 8, 16., 32, ... (Halt 2 hoch 0, 1, 2, 3, ....)
Nach dem Komma hätten wir Wertigkeiten von 2 hoch -1, -2, -3, .... was dann den Werten:
0,5
0,25
0,125
0,0625
...
entspricht.

Da erkennst Du erst einmal schon, dass es keine wirklich einfache Darstellung von 0,1 (Dezimalsystem) gibt.

Da die Genauigkeit, mit der eine Zahl gespeichert wird, begrenzt ist, ist keine exakte Darstellung möglich und somit muss es zu diesen Ungenauigkeiten kommen.

Intern wird dann schon etwas gerundet. Der gespeicherte Wert bei 0.1 ist näher an 0,1 als an 0,10000000001 oder so (Die Anzahl der 0 ist jetzt nicht exakt ... ) aber nach der Rechnung hat man dies dann so nicht mehr und der Wert kommt nun näher an den Wert, den Du da gesehen hast.

Hier ist dann auch die Schlußfolgerung wichtig, denn diese Ungenauigkeiten können sich von Berechnung zu Berechnung immer weiter Vergrößern.
 

SpaceCookie

Neues Mitglied
Schauen wir uns nur einmal duale Zahlen an:

Vor dem Komma haben wir die Wertigkeiten 1, 2, 4, 8, 16., 32, ... (Halt 2 hoch 0, 1, 2, 3, ....)
Nach dem Komma hätten wir Wertigkeiten von 2 hoch -1, -2, -3, .... was dann den Werten:
0,5
0,25
0,125
0,0625
...
entspricht.

Da erkennst Du erst einmal schon, dass es keine wirklich einfache Darstellung von 0,1 (Dezimalsystem) gibt.

Da die Genauigkeit, mit der eine Zahl gespeichert wird, begrenzt ist, ist keine exakte Darstellung möglich und somit muss es zu diesen Ungenauigkeiten kommen.

Intern wird dann schon etwas gerundet. Der gespeicherte Wert bei 0.1 ist näher an 0,1 als an 0,10000000001 oder so (Die Anzahl der 0 ist jetzt nicht exakt ... ) aber nach der Rechnung hat man dies dann so nicht mehr und der Wert kommt nun näher an den Wert, den Du da gesehen hast.

Hier ist dann auch die Schlußfolgerung wichtig, denn diese Ungenauigkeiten können sich von Berechnung zu Berechnung immer weiter Vergrößern.
Ok verstehe, vielen Dank. Das heißt aber, Runden (in meinem Fall auf eine Nachkommastelle) sollte das lösen, oder?
 

LimDul

Top Contributor
Ja, das würde das Problem lösen.

Solche Probleme hat man immer wenn man Fließkommazahlen rechnet. Es gibt da eigentlich hauptsächlich zwei Strategien:

- Runden auf die relevante Stellenanzahl. Je nach Rechnung, Anzahl Operationen und benötigter Genauigkeit kann es aber trotzdem sein, dass man am Ende ein "falsches" Ergebnis hat. (Wenn man z.B. bei einer Rechnung unbedingt 14 Nachkommastellen braucht und zig- Divsionen, Additionen etc. durchführt). Für die meisten praktischen Belange reicht es
- Einen Datentyp nehmen, der Operationen, die genau möglich sind, auch genau macht wie BigDecimal. Nachteil ist, dass man dann nicht einfach c = a + b schreiben kann sondern c=a.add(b) schreiben muss und insbesondere manche Rechenoperationen da teurer sind oder nicht so einfach möglich sind (Logarithmus und Co z.B.). BigDecimal nimmt man daher in der Regel wenn Abweichungen nicht tolerabel sind - also alles rund um Geldbeträge meistens.
 

White_Fox

Top Contributor
- Einen Datentyp nehmen, der Operationen, die genau möglich sind, auch genau macht wie BigDecimal. Nachteil ist, dass man dann nicht einfach c = a + b schreiben kann sondern c=a.add(b) schreiben muss und insbesondere manche Rechenoperationen da teurer sind oder nicht so einfach möglich sind (Logarithmus und Co z.B.). BigDecimal nimmt man daher in der Regel wenn Abweichungen nicht tolerabel sind - also alles rund um Geldbeträge meistens.
Außerdem ist die Berechnung dabei ein Riesenaufriß.

Sowas wie c = a + b; rechnet die CPU in einem Takt oder sogar weniger durch. Ich habe mit BigDecimal noch nie gearbeitet, daher unausgegorenes Halbwissen, würde aber trotzdem mal vermuten daß da im Wesentlichen in Software "per Hand" gerechnet wird. Also anstatt einfach zwei Register in der CPU zu verknüpfen, z.B. über ein unvorhersehbar langes Array zu iterieren und in einfacher zu bewältigenden Häppchen wie Integer zu rechnen und mit dem Überlauf beim nächsten weiterzumachen.

Wenn du irgendwelche Matritzenoperationen z.B. in Simulationsprogrammen so durchführen willst, wo eine Matrix mehrere hundert oder gar tausend Zeilen/Spalten hat, kann das schnell richtig lange dauern.
 

Robert Zenz

Top Contributor
Natuerlich braucht ein BigDecimal mehr Rechenleistung, aber in 99.9999% der Faelle ist der Unterschied in der Performance absolut unerheblich und zu ignorieren. Meiner Erfahrung nach schlieszen sich aber auch die Anforderungen "exaktes Ergebnis" und "schnelles Ergebnis" aus beziehungsweise treffen nie aufeinander. Also wenn du ein exaktes Ergebnis brauchst (BigDecimal), ist die Geschwindigkeit auf dieser Ebene nicht relevant, zum Beispiel in ERP Systemen. Wenn du wirklich Geschwindigkeit brauchst (float/double) ist dir egal ob das Ergebnis wirklich exakt ist, zum Beispiel in Grafikanzeige.

Aber wie gesagt, wir reden hier von Performance- und Speicher-Unterschieden auf schon fast esoterischer Ebene. Alternativ kann man immer einen int/long verwenden in der kleinsten Einheit, also zum Beispiel nicht "5,20 Euro" sondern "520 Eurocent".
 

White_Fox

Top Contributor
Ich gebe dir zwar Recht daß Großgeschütze wie BigDecimal nur selten notwendig sind, aber:
Meiner Erfahrung nach schlieszen sich aber auch die Anforderungen "exaktes Ergebnis" und "schnelles Ergebnis" aus beziehungsweise treffen nie aufeinander. Also wenn du ein exaktes Ergebnis brauchst (BigDecimal), ist die Geschwindigkeit auf dieser Ebene nicht relevant, zum Beispiel in ERP Systemen. Wenn du wirklich Geschwindigkeit brauchst (float/double) ist dir egal ob das Ergebnis wirklich exakt ist, zum Beispiel in Grafikanzeige.
Ist das so? Deine Beispiele sagen mir jetzt wenig, aber wenn ich z.B. an Spice-Simulationen elektrischer Netzwerke denke, hast du von Natur aus oft schon sehr große Zahlenbereiche: Kapazitäten im Picofaradbereich, Nano- oder gar Picosekunden und darunter, bei Widerständen mit mehreren Mega- oder gern auch Gigaohm, spannt schonmal einen sehr weiten Zahlenbereich auf. 10^-15 bis 10^12 kann man da schonmal abdecken wollen. Bei zwei Operanden innerhalb derselben Operation.

Ähnlich dürfte es auch bei FEM-Simulationen aussehen, wird gerne für die Simulation von Kräften in einem Körper (z.B. Schwingung von Maschinengehäusen) oder Fluidsystemen oder bei der Simulation elektromagnetischer Felder.

Das wären Beispiele, wo ich an BigDecismal denken würde und bei all diesen Beispielen können schnell sehr lang andauernde, große Berechnungen entstehen. Ich habe heute öfter mal ein längeres Päuschen machen müssen wegen Wartezeit aus genau diesem Grund.
 

LimDul

Top Contributor
Hier im Projekt ist es umgekehrt - wer double (oder gar float) verwendet, bekommt was auf die Finger, hier wird nur BigDecimal (bzw. ein Wrapper drum rum für etwas mehr Convience) verwendet. Es kommt halt immer auf die Umgebung und Anforderungen an.
 
M

Mart

Gast
Du kannst es solange multiplizieren mit zehn dass es keine nachkommastellen mehr gibt und dann entsprechen die zahl genauso oft durch zehn teilen dadurch könnte man es umgehen zu runden
 

LimDul

Top Contributor
Du kannst es solange multiplizieren mit zehn dass es keine nachkommastellen mehr gibt und dann entsprechen die zahl genauso oft durch zehn teilen dadurch könnte man es umgehen zu runden
Nein, das ist keine Lösung sondern falsch. Das Problem besteht dann weiterhin.

Der Knackpunkt ist nicht Fragen Nachkommastellen, sondern die Verwendung von Fließkommazahlen. Das heißt, zum einen müsste man die Zahl dann auch in ein int/long umwandeln und zum anderen tritt das Problem auch beim Multiplizieren und dividieren auf.
 
K

kneitzel

Gast
Man könnte die Problematik mit der Ungenauigkeit beim Wandel in das duale System durch eine Darstellung mit 10er Exponent.
Da gibt es dann keine Normalisierung zu 1,xxxx aber eine exponentiell Darstellung ist denkbar:
49 E -1 = 4,9
5 E 0 = 5

Zur Subtraktion muss man den Exponent anpassen:
(5 × 10) E (0-1)
Wenn es bei der Mantisse oder dem Exponenten ein Überlauf gibt, dann muss man das behandeln.

Aber so hat man 50E-1 - 49E-1 = 1E-1

Theoretisch kein Thema ...
 

mihe7

Top Contributor
Ist ja ganz knapp dran, aber trotzdem falsch. Gibt es dafür ne Erklärung? Warum passiert das? Und: Kann ich das einfach durch Math.round() lösen?
1/10 ist im Dualsystem genau so wenig exakt darstellbar wie 1/3 im Dezimalsystem. Die Brüche lassen sich mit einer begrenzten Zahl an Nachkommastellen im jeweiligen Zahlensystem nicht genau darstellen. Der Umgang mit solchen Problemen unterscheidet sich vom Dezimalsystem nicht.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
JordenJost char variable funktioniert irgendwie nicht a+b ergibt nicht à Java Basics - Anfänger-Themen 4
D Datentypen LocalDate.parse() ergibt Fehler Java Basics - Anfänger-Themen 5
G Taschenrechner ergibt Fehler in if-Abfrage Java Basics - Anfänger-Themen 6
L Anzahl der Paare deren Summe = 0 ergibt berechnen Java Basics - Anfänger-Themen 0
E Was ergibt trim() auf einen leeren String Java Basics - Anfänger-Themen 3
S string index out of range - es ergibt keinen Sinn Java Basics - Anfänger-Themen 6
J .txt Datei "einlesen "und in String speichern ergibt immer NULL Java Basics - Anfänger-Themen 17
K Schnitt zweier Ebenen ergibt Gerade Java Basics - Anfänger-Themen 10
E Client ergibt NULL? Java Basics - Anfänger-Themen 24
M Variablen Zinseszinsberechnung - Variable ergibt keinen Sinn Java Basics - Anfänger-Themen 15
D Problem mit Nachkommastellen <%=Double.valueOf(35/1000)%> ergibt 0.0? Java Basics - Anfänger-Themen 3
2 double multipliziert mit int ergibt Rundungsfehler Java Basics - Anfänger-Themen 5
B Division ergibt null Java Basics - Anfänger-Themen 7
DrahtEck Warum bekomme ich ein "minus" ausgegeben Java Basics - Anfänger-Themen 2
R Anfänger: Ausgabe kommt minus raus? Java Basics - Anfänger-Themen 6
K Was tut minus shiften Java Basics - Anfänger-Themen 1
J Erste Schritte replace von minus Zeichen wird nicht gemacht Java Basics - Anfänger-Themen 7
fill0soph Wieso ist "Minus-Unendlich" == 1? Java Basics - Anfänger-Themen 4
J getYear() = Jahr minus 1900??? Java Basics - Anfänger-Themen 2
richis-fragen JTable den angezeigten WERT nicht den Wert aus dem Model ausgeben. Java Basics - Anfänger-Themen 3
richis-fragen JTable Header ausgeblendete (width = 0) nicht per mouseDragged aufziehen. Java Basics - Anfänger-Themen 9
M Ausgabe einer ArrayList ensteht nur als Hashcode, nicht als Objekt Java Basics - Anfänger-Themen 16
K Warum wird mir auf der Konsole des Servers nicht "xxxx" angezeigt (Server/Client) Java Basics - Anfänger-Themen 4
K Warum wird hier nur etwas in eine txt Datei geschrieben und nicht in alle drei (InputStream/OutputStream/Reader/Writer) Java Basics - Anfänger-Themen 1
richis-fragen JTable effektiv angezeigter Text ausgeben nicht Inhalt vom Model Java Basics - Anfänger-Themen 9
S nach Import von jars (PLC4x) in Eclipse kann nicht mehr compiliert werden Java Basics - Anfänger-Themen 9
J Datenüberwachung funktioniert nicht Java Basics - Anfänger-Themen 9
S Wie debugge ich dies am besten: SingleThreadExecutor führt Task nicht aus..? Java Basics - Anfänger-Themen 29
H JDK installieren jdk-21 wird nicht erkannt Java Basics - Anfänger-Themen 13
N Klassen Hintergrundfarbe in JPanel ändert sich nicht Java Basics - Anfänger-Themen 3
K Warum wird mir "Empfangen vom Client:" nicht sofort ausgegeben(Server/Client) Java Basics - Anfänger-Themen 3
mo13 JTextField funktioniert nicht Java Basics - Anfänger-Themen 4
J .jar datei öffnen funktioniert nicht Java Basics - Anfänger-Themen 17
M Methode zielnah zeigt das gewünschte Ausgabe nicht an Java Basics - Anfänger-Themen 3
K Verstehe Rekursion nicht ganz Java Basics - Anfänger-Themen 7
M OOP Brüche nicht richtig berechnen Java Basics - Anfänger-Themen 3
N Ich kriege ganze zeit die Fehlermeldung "Inhalt der Zwischenablage kann nicht in die ausgewählten Elemente eingefügt werden" hat jemand eine Lösung? Java Basics - Anfänger-Themen 6
K TicTacToe belegtes feld nicht neu besetzbar Java Basics - Anfänger-Themen 1
K TicTacToe belegtes Feld nicht neu besetzbar Java Basics - Anfänger-Themen 3
A Warum wird mein jdk nicht gefunden? Java Basics - Anfänger-Themen 3
M Queue-Datenstruktur: nach dem Elementen entfernen, das Ergebnis ist immer noch nicht optimal. Java Basics - Anfänger-Themen 3
K Programm compilierbar aber nicht ausführbar... Java Basics - Anfänger-Themen 21
N Hey Leute und zwar versuche ich gerade ein 2D Spiel zu Programmieren aber die Figur will sich nicht nach links oder rechts bewegen :( Java Basics - Anfänger-Themen 12
G Mit jPackage erstellte EXE funktioniert nicht Java Basics - Anfänger-Themen 2
N BMI Rechner Was haltet ihr von dem Code habt ihr Verbesserungsvorschläge weil design teschnisch ist das nicht das geilste würde das gerne überarbeiten Java Basics - Anfänger-Themen 12
G Robot funktioniert nicht bei SelectionListener Java Basics - Anfänger-Themen 6
D MacOS: PDF erstellen geht nicht Java Basics - Anfänger-Themen 1
G Kann Java-Programm nicht als jar aufrufen, auch als EXE nicht Java Basics - Anfänger-Themen 19
J jar Befehl wird nicht erkannt Java Basics - Anfänger-Themen 7
missy72 Erste Schritte (nicht) Deterministischer endlicher Automat Java Basics - Anfänger-Themen 9
T Getter/Setter - wie sieht ein Setter aus? Und wie nicht? Java Basics - Anfänger-Themen 34
T catch(InputMismatchException) wird nicht ausgefürt/erkannt Java Basics - Anfänger-Themen 12
T Methode akzeptiert String nicht Java Basics - Anfänger-Themen 18
P Netbeans installation geht nicht Java Basics - Anfänger-Themen 26
R RegEx funktioniert nicht Java Basics - Anfänger-Themen 14
T HashMap Lsite gibt die sachen nicht aus wie gewollt. Java Basics - Anfänger-Themen 3
H Counter durch gepresste Taste nur auf 1 erhöhen und nicht durchzählen lassen Java Basics - Anfänger-Themen 7
S 2 Reihen ratio-btn, eine Reihe funktioniert andere nicht Java Basics - Anfänger-Themen 4
T scanner nicht erkannt Java Basics - Anfänger-Themen 3
monsterherz Punkt Notation funktioniert nicht Java Basics - Anfänger-Themen 4
monsterherz Fehler Semikolon fehlt - ich weiss aber nicht wo da noch eines hin sollte... Java Basics - Anfänger-Themen 21
R Java kann nicht installiert werden Java Basics - Anfänger-Themen 8
marcelnedza Finde meinen Fehler in einer Methode nicht, Java Karol Java Basics - Anfänger-Themen 15
monsterherz einfache Methode mit Fehler den ich nicht finde Java Basics - Anfänger-Themen 21
monsterherz if / else if mit Fehler den ich leider nicht finde Java Basics - Anfänger-Themen 11
D Jar Datei startet unter Linux nicht Java Basics - Anfänger-Themen 3
KeinJavaFreak Erste Schritte Programm "Java(TM) Platform SE binary " nicht vorhanden Java Basics - Anfänger-Themen 1
KeinJavaFreak Erste Schritte Java "Executable Jar File" nicht vorhanden Java Basics - Anfänger-Themen 1
M Konstruktor-Aufruf im Konstruktor, aber nicht am Anfang? Java Basics - Anfänger-Themen 4
G Variable aktualisiert sich nicht in rekursiver Methode Java Basics - Anfänger-Themen 4
Darkherobrine9 Import klappt nicht Java Basics - Anfänger-Themen 7
N Programm Funktioniert mit .txt Datei aber nicht mit .rtf Datei Java Basics - Anfänger-Themen 2
R Compiler-Fehler Variable wird nicht gefunden bzw. erkannt? Java Basics - Anfänger-Themen 2
_so_far_away_ Inventarisierungssystem brauche switch Cases und weiß nicht, wie ich e implementieren muss Java Basics - Anfänger-Themen 5
P BeforeEach AfterEach werden nicht ausgeführt. Java / Selenium Java Basics - Anfänger-Themen 4
I Erste Schritte Einfache Datenbank-Webseite erstellen als Nicht-IT-lerin Java Basics - Anfänger-Themen 24
N Interpreter-Fehler Compiler zeigt keine Fehler an, aber das Programm läuft nicht (BlueJ) Java Basics - Anfänger-Themen 2
D Quellcode für cmd funktioniert nicht Java Basics - Anfänger-Themen 9
C Kann mir jemand sagen warum ich nicht mal rechnen kann ? Java Basics - Anfänger-Themen 32
K Java Lotto Spiel; ich komme nicht weiter Java Basics - Anfänger-Themen 15
A JavaFX-Anwendung läuft nicht mit Selenium WebDriver Java Basics - Anfänger-Themen 0
T Meine Klasse wird nicht gefunden Java Basics - Anfänger-Themen 1
T Wie kann man es machen das ein Objekt nicht übermalt wird Java Basics - Anfänger-Themen 2
H Cast von Float nach String klappt nicht Java Basics - Anfänger-Themen 12
heinrich172 Methoden Trotz gleichem Element stimmt Vergleich nicht? Java Basics - Anfänger-Themen 7
I Entity Objekt nicht gefunden -> Webhook empfangen in der gleichen Methode (Transaktion) Java Basics - Anfänger-Themen 37
K warum kann ich das Objekt nicht erstellen ? Java Basics - Anfänger-Themen 2
MiMa Ungültiges Datum wird nicht erkannt ?? Java Basics - Anfänger-Themen 6
J Meine Mails gehen nicht raus Java Basics - Anfänger-Themen 8
Zrebna Kann Java Programm nicht in Konsole ausführen Java Basics - Anfänger-Themen 1
S Ist JDK jetzt free oder nicht? Java Basics - Anfänger-Themen 5
K Warum läuft das Programm nicht(bzw. nicht richtig) Java Basics - Anfänger-Themen 4
B Explizit Array definieren geht nicht? Java Basics - Anfänger-Themen 14
M Methoden Methode 'wiederhole' nicht gefunden (Uebersetzungsfehler) Java Basics - Anfänger-Themen 1
D Eclipse will nicht auslesen Java Basics - Anfänger-Themen 6
Temsky34 Array IndexOf nicht verfügbar Java Basics - Anfänger-Themen 18
TeacherMrSSimon Schachspiel, Werte in Figur eintragen klappt nicht Java Basics - Anfänger-Themen 23
B von Java/Eclipse verwendete Datei existiert gar nicht? Java Basics - Anfänger-Themen 6
ms_cikar Bin to Float convertieren funktioniert nicht Java Basics - Anfänger-Themen 24
B Schrankensystem mit Farberkennung für Flashgame funktioniert nicht wie geplant Java Basics - Anfänger-Themen 4

Ähnliche Java Themen

Neue Themen


Oben