• Wir präsentieren Dir heute ein Stellenangebot für einen Java Entwickler - m/w/d in Augsburg, München, Stuttgart oder Bamberg. Hier geht es zur Jobanzeige

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

SpaceCookie

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!
 
kneitzel

kneitzel

Top Contributor
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

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?
 
L

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.
 
W

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

Robert Zenz

Aktives Mitglied
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".
 
W

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.
 
L

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.
 
Mart

Mart

Mitglied
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
 
L

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.
 
kneitzel

kneitzel

Top Contributor
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

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
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
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
S Schleife funktioniert nicht Java Basics - Anfänger-Themen 2
H So viele Fehlermeldungen, dass ich nicht weiß wo das Problem ist. Java Basics - Anfänger-Themen 6
U Hauptklasse kann nicht gefunden werden Java Basics - Anfänger-Themen 8
B Ausgabe in TextArea funktioniert nicht Java Basics - Anfänger-Themen 2
OSchriever Jar-Programm läuft auf Windows aber nicht auf Linux(Raspberri Pi4) Java Basics - Anfänger-Themen 22
J JTable Titel wird nicht angezeigt Java Basics - Anfänger-Themen 6
R Array mit Unter- und Obergrenze ganze Zahlen dazwischen erscheinen nicht Java Basics - Anfänger-Themen 1
T Methode schreiben, die einem Array ein Stringelement hinzufügt, wenn dieses noch nicht enthalten ist. Java Basics - Anfänger-Themen 6
C java.sql Statement kann nicht geschlossen werden Java Basics - Anfänger-Themen 9
B Nicht reproduzierbarer Fehler bei Kompilierung - Shortcut "Bereinigung" Compiler ? Java Basics - Anfänger-Themen 4
Henri Webservice Delete und Update Methode funktioniert nicht Java Basics - Anfänger-Themen 27
F Wann ist es eine Instanz und wann nicht? Java Basics - Anfänger-Themen 1
E Warum lässt sich eine Klasse nicht starten, wenn eine andere Klasse in dem Modul fehlerhaft ist? Java Basics - Anfänger-Themen 1
UnknownInnocent Vererbung Attributtyp in Super-Klasse noch nicht festlegen Java Basics - Anfänger-Themen 1
U anfänger braucht hilfe . wir konnten die aufgaben nicht beantworten Java Basics - Anfänger-Themen 5
LetsSebi Dateien werden nicht in Zip gespeichert Java Basics - Anfänger-Themen 1
N Erste Schritte HelloWorld möchte einfach nicht laufen Java Basics - Anfänger-Themen 11
H GridPane wird nicht angezeigt Java Basics - Anfänger-Themen 0
UnknownInnocent Generics: Klassen die Interface implementieren, aber selbst nicht das Interface sind Java Basics - Anfänger-Themen 8
V Anfängerfrage: HelloWorld läuft nicht Java Basics - Anfänger-Themen 3
C Was machen mit nicht mehr verwendeten Instanzen ? Java Basics - Anfänger-Themen 18
J Array Elemente werden nicht gefunden! Java Basics - Anfänger-Themen 6
B Methoden warum macht die Methode nicht das was ich erwarte? Java Basics - Anfänger-Themen 2
Y Aufruf von Methode nicht möglich. Java Basics - Anfänger-Themen 2
T Ich habe eine Variabel die nicht Methoden übergreifend ist. Kann mir jemand Helfen :) Java Basics - Anfänger-Themen 5
H Endkapital wird nicht korrekt ausgegeben. Java Basics - Anfänger-Themen 5
U Teilergebniss mit 0 nicht ausgeben Java Basics - Anfänger-Themen 3
R Ich sehe meinen fehler nicht Java Basics - Anfänger-Themen 8
IamArctic Quaxli Tutorial, Rotorblätter bewegen sich nicht mehr Java Basics - Anfänger-Themen 4
J ActionListener von JCheckBox im Knoten von JTree funktioniert nicht Java Basics - Anfänger-Themen 2
C System.out.println - Parameterübergabe funktioniert nicht Java Basics - Anfänger-Themen 2
M Warum werden character, die Leerzeichen sind, nicht korrekt verarbeitet? Java Basics - Anfänger-Themen 2
C Methodenrückgabe wird in der main nicht berücksichtigt Java Basics - Anfänger-Themen 2
C Methoden können nicht auf Instanzvariable der Klasse zugreifen Java Basics - Anfänger-Themen 3
JD_1998 Hilfsmethode if return funktioniert nicht Java Basics - Anfänger-Themen 2
O if Abfrage erkennt String nicht Java Basics - Anfänger-Themen 1
P Klassenübergreifende Ausgabe mittels "getter" nicht möglich Java Basics - Anfänger-Themen 21
Dimax RegEx funktionieren nicht Java Basics - Anfänger-Themen 7
C JButton Text 2 Mal ändern funktioniert nicht Java Basics - Anfänger-Themen 8
kodela Hauptklasse wird nicht gefunden Java Basics - Anfänger-Themen 3
H Befehl wird nicht ausgeführt - System.out.println Java Basics - Anfänger-Themen 3
P Bedingung in Schleife wird nicht ausgeführt Java Basics - Anfänger-Themen 5
J Warum löst der Changelistener nicht aus ? Java Basics - Anfänger-Themen 5
P Variablen HttpResponse.getBody() wird automatisch org.json Object und kann nicht zu json.simple Object gecastet werden? Java Basics - Anfänger-Themen 7
B Interface List - Objekt übergeben? Einzelnes Objekt geht, aber Liste nicht? Java Basics - Anfänger-Themen 4
T Main startet nicht bei vorgegebenen Code Java Basics - Anfänger-Themen 41
T Eclipse deinstallieren nicht vorhanden? Java Basics - Anfänger-Themen 4
T HelloWorld startet nicht Java Basics - Anfänger-Themen 14
M Regex nur Zahlen und Punkt zulassen, Keine Eingabe(Leeres TextFeld) nicht zulassen Java Basics - Anfänger-Themen 6
N Selection Algorithmus: Methode wird nicht erkannt (BlueJ) Java Basics - Anfänger-Themen 3
T % funktioniert nicht Java Basics - Anfänger-Themen 2
F JMenuItem Kann nicht nach einem String benannt werden... Java Basics - Anfänger-Themen 11
B Fehler, aber ich weiß nicht warum Java Basics - Anfänger-Themen 3
P module-info findet zweites Paket nicht Java Basics - Anfänger-Themen 1
J Fehler im Code, aber ich weiß nicht wieso! Java Basics - Anfänger-Themen 6
A Speicherbereich von Array nicht zusammenhängend? Java Basics - Anfänger-Themen 8
M Else wird nicht ausgeführt. Java Basics - Anfänger-Themen 5
B Erste Schritte Guice Injection nicht in jeder Klasse möglich Java Basics - Anfänger-Themen 2
Zrebna Programm kann aus der Konsole nicht gestartet werden (in der IDE läuft es) Java Basics - Anfänger-Themen 2
S Input/Output Reader/Writer finden file nicht Java Basics - Anfänger-Themen 3
K Probleme bei der Ausgabe - komme nicht weiter :/ Java Basics - Anfänger-Themen 15
D e(fx)clipse installieren funktioniert nicht Java Basics - Anfänger-Themen 3
I Sortiert eine HashMap nicht gleich wie eine ArrayList? Java Basics - Anfänger-Themen 1
E Methoden Action Event wird nicht vollständig ausgeführt Java Basics - Anfänger-Themen 3
D GPIO Nutzung mit Pi4J Library auf Raspberry funktioniert nicht Java Basics - Anfänger-Themen 3
F Java GUI-PaintComponent funktioniert nicht Java Basics - Anfänger-Themen 1
J equals funktioniert nicht - Warum Java Basics - Anfänger-Themen 13
S Konstruktor passt nicht zum Rest Java Basics - Anfänger-Themen 11
V Erste Schritte Die Nuller bei double NICHT abschneiden Java Basics - Anfänger-Themen 4
L hilfe run button funktioniert nicht Java Basics - Anfänger-Themen 13
C Beispiel-Code mit Pair wird nicht compiliert. Java Basics - Anfänger-Themen 8
S Integer Wert wird nicht übernommen Java Basics - Anfänger-Themen 2
F Switch case wird als char nicht erkannt.... Java Basics - Anfänger-Themen 6
T Javafx ListView kann nicht gefüllt werden. Java Basics - Anfänger-Themen 6
V Boolean Wert nicht richtig erkannt Java Basics - Anfänger-Themen 4
H Eclipse kann nicht gestartet werden .... Java Basics - Anfänger-Themen 15
NeoLexx Variable für Array wird nicht korrekt übergeben Java Basics - Anfänger-Themen 45
R Warum werden hier nur die grün und orangen Linien ausgegeben und der Rest unten nicht? Java Basics - Anfänger-Themen 5
I Array funktioniert nicht. Java Basics - Anfänger-Themen 2
M BorderLayout, 2Panels, EAST wird nicht angezeigt ?? Java Basics - Anfänger-Themen 2
S Kontrollieren, ob ein Jlabel nicht sichtbar ist Java Basics - Anfänger-Themen 6
J Eckige Klammern werden nicht erkannt Java Basics - Anfänger-Themen 1
Dimax In Java File (nicht in Java Projekt) mysql Driver importieren Java Basics - Anfänger-Themen 3
K File wird in der .Jar nicht gefunden Java Basics - Anfänger-Themen 3
K Kann nicht starten Java Basics - Anfänger-Themen 30
A Haben KNNs ein Gedächtnis, lernen etwas oder verändern sich, während sie nicht trainieren, aber aktiv sind? Java Basics - Anfänger-Themen 3
tom.j85 Map - Values nicht korrekt ersetzt (Abzählspiel) Java Basics - Anfänger-Themen 13

Ähnliche Java Themen

Anzeige

Neue Themen


Oben