0.009 wird zu 0.0090

Status
Nicht offen für weitere Antworten.

me.toString

Bekanntes Mitglied
Moin!

Habe eben ewig nach einem Fehler in meinem Programm gesucht ... und nu muss ich feststellen, dass Java selber das Problem ist:
Code:
System.out.println(0.009);
Aber es wird nicht 0.009 ausgegeben sondern 0.0090 !!! Mit internen Darstellungsfehlern kann das ja nix zu tun haben, dann würde ja sowas wie 0.0090000000000001 rauskommen. Hat von euch schon mal jemand so ein Problem gehabt? Man könnte natürlich dahergehen und die letzten Nullen abscheiden... aber das muss doch auch eleganter gehen !?
 

Kaffeebohne

Bekanntes Mitglied
Das ist ja witzig. Stimmt. Und bei einer zusätzlichen Null wirds 9.0E-4 :)

Warum würde mich jetzt aber auch interessieren.
 

clemson

Bekanntes Mitglied
Code:
package org.javaforum.y06.april.PrintF;

import java.text.DecimalFormat;

public class DoublePrint
{

	public static void main(String[] args)
	{
		double d = 0.009d;
		DecimalFormat format = new DecimalFormat("#.###");
		System.out.println(format.format(d));
	}

}
 

The_S

Top Contributor
clemson hat gesagt.:
Code:
package org.javaforum.y06.april.PrintF;

import java.text.DecimalFormat;

public class DoublePrint
{

	public static void main(String[] args)
	{
		double d = 0.009d;
		DecimalFormat format = new DecimalFormat("#.###");
		System.out.println(format.format(d));
	}

}

Das ist aber nicht die Antwort auf die Frage ... :autsch:
 

Murray

Top Contributor
Ich würde das als Fehler im JDK ansehen; die Doku besagt ja
1. PrintStream#println( double) funktioniert wie PrintStream#print( double)
2. PrintStream#print( double) funktioniert wie String#valueOf( double)
3. String#valueOf( double) funktioniert wie Double#toString( double)
4. Für Double#toString( double) gilt:
How many digits must be printed for the fractional part of m or a? There must be at least one digit to represent the fractional part, and beyond that as many, ****but only as many****, more digits as are needed to uniquely distinguish the argument value from adjacent values of type double. That is, suppose that x is the exact mathematical value represented by the decimal representation produced by this method for a finite nonzero argument d. Then d must be the double value nearest to x; or if two double values are equally close to x, then d must be one of them and the least significant bit of the significand of d must be 0.

Wenn ich jetzt folgendes Testprogramm ausführe:
Code:
public class Test {

	public static void main( String[] args) {
		
		test( 0.009);
	
	}
	
	public static void test( double d) {
		System.out.println( "test: d = " + d);
		long l = Double.doubleToLongBits( d);
		for ( int i=-3; i<=3; i++) {
			long ll = l + i;
			System.out.println( i + "\t " + ll + "\t " + Double.longBitsToDouble( ll)); 
		
		}
	}
	

}

dann sehe ich folgende Ausgabe:
-3 4576341768551784248 0.008999999999999994
-2 4576341768551784249 0.008999999999999996
-1 4576341768551784250 0.008999999999999998
0 4576341768551784251 0.0090
1 4576341768551784252 0.009000000000000001
2 4576341768551784253 0.009000000000000003
3 4576341768551784254 0.009000000000000005


Also: die interne Repräsentation von 0.009 ist 4576341768551784251. Dann ist der nächstkleinere, mit double darstellbare Wert offenbar 0.008999999999999998; der nächstgrößere Wert dann 0.009000000000000001. Insofern wäre also bereits 0.009 eindeutig von den angrenzenden beiden Werten unterscheidbar, und da ja nicht mehr Nachkommastellen ausgegeben werden solle, als zur Unterscheidung notwendig, ist das Verhalten hier anders als in der Dokumentation.

IMHO also ein Bug für Erbsenzähler :wink:
 
T

teufel

Gast
Hi ehli75,
das hat was mit dem datentyp zu tun.
Jede Zahl wird binär gespeichert. Ich weiß zwar nicht wie das bei dem datentyp double aussieht, aber normalerweiße wird so eine zahl in einem datenwort gespeichert. So ein Wort hat immer eine bestimmte länge (z.b. besteht immer aus 6 bytes das entspricht 48 bits). Werden nicht alle 6 bytes benötigt, wird am schuss einfach eine null rangehängt (Alle ungebrauchten bytes werden zu 0). Nun weiß die Ausgabe ja nicht was man da eingegeben hat und gibt daher das ganze Wort aus (Samt den von Programm hinzugefügten nullen).

Mfg teufel
 

Kawa-Mike

Mitglied
Wenn es wirklich mit der Internen Darstellung der Zahlen zu tun hat, könnte es sogar Plattform- oder JVM-abhängig sein.
Ich habe es mal getestet mit

1.) Win2000 und Java 1.5.0_06 von SUN
2.) SuseLinux 9.0 und Java 1.4.2-b28, auch von SUN

Beide Rechner haben eine Intel Pentium-Processor.
Bei beiden Tests wurde die 0 angehängt.
Interessant wäre es auch mit einem Rechner mit AMD-CPU, oder unter einem ander OS z.B. MAC.
 

me.toString

Bekanntes Mitglied
Hobbit_Im_Blutrausch hat gesagt.:
warum dass so ist. Also warum bei einer Fließkommazahl immer eine 0 hinter die letzte Kommazahl gehängt wird sobald diese letzte Zahl die einzigste ist, die != 0 ist.
Das ist nicht immer so, sondern nur bei den Zahlen 0.001, 0.002, ..., 0.009. Sonst müsste ja bei System.out.println(0.9) rauskommen 0.90 ... tuts aber nicht.

Das es nun 4 Nachkommastellen sind... mein Gott, dass kann ich dem Kunden schon irgendwie verklickern ... aber nun kommt noch das Problem hinzu, dass durch die "neue" 0 mein Wert falsch wird. Ursprünglich hatte ich die Zahl 0.00917119565217395, die auf 3 Stellen nach dem Komma gerundet werden soll ...das hat auch wunderbar geklappt: 0.009. Wennich nun aber System.out.println(zahl) mache, kommt eben 0.0090 raus ... und das ist, abgesehen davon, dass es auf einmal 4 Nachkommastellen sind, nicht korrekt ... dann müsste es heissen 0.0092!
Bei wievielen Zahlen tritt das denn noch auf? ... da kann man sich ja auf nix verlassen.
Eben hab ich bei SUN in der Bug-Database was dazu gefunden ... aber so richtig schlau werd ich da nicht draus (mein Englisch ist nicht das aller beste) ... aber wenn ich mir überlege, dass der Bug (so fern es denn einer ist ... vielleicht wird es in der nächsten Java-Version als Feature gefeiert ... :wink:) 2001 eingestellt wurde, ist es schon traurig, dass da Java-Intern noch nix passiert ist ...
 

byte

Top Contributor
Die Antwort auf die Frage hat Clemson oben doch schon gepostet. Du solltest in Java für die Ausgabe von Dezimalzahlen immer ein NumberFormat bzw. DecimalFormat verwenden, weil Du nur so sichergehen kannst, die dezimalen Ungenauigkeiten zu umgehen. Diese Ungenauigkeiten sind übrigens keine Schwäche von Java sondern kommen daher, dass Java (und jede andere Computersprache auch) intern binär rechnen, das Binärsystem dezimal jedoch ungenauer ist als das 10er System.

Vergleiche dazu:

Code:
DecimalFormat df = new DecimalFormat("#.###############");
		
float z = 0.009f;
		
System.out.println(df.format(z));
System.out.println(z);
 

The_S

Top Contributor
ehli75 hat gesagt.:
Hobbit_Im_Blutrausch hat gesagt.:
warum dass so ist. Also warum bei einer Fließkommazahl immer eine 0 hinter die letzte Kommazahl gehängt wird sobald diese letzte Zahl die einzigste ist, die != 0 ist.
Das ist nicht immer so, sondern nur bei den Zahlen 0.001, 0.002, ..., 0.009. Sonst müsste ja bei System.out.println(0.9) rauskommen 0.90 ... tuts aber nicht.

Stimmt! Ich frag mich nur gerade was ich dann gestern rumprobiert hab, dass ich da draufgekommen bin ???:L
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
kodela ArrayList wird nicht komplett gespeichert Allgemeine Java-Themen 3
kodela HelpSet wird nicht gefunden Allgemeine Java-Themen 8
N Lwjgl 3d Objekt wird schmaler, wenn es sich dreht Allgemeine Java-Themen 0
D Linux, Java-Version wird nicht erkannt bzw. welche Einstellung fehlt noch? Allgemeine Java-Themen 19
berserkerdq2 Wenn ich einfach eine GIF in den Scenebuilder als Bild reinpacke, wird das dann asl Gif angezeigt Allgemeine Java-Themen 1
G Popup wird nicht sichtbar Allgemeine Java-Themen 9
8u3631984 Funktions Parameter mit Lombok "NonNull" annotieren wird in Jacococ Testcoverage nicht herausgefiltert Allgemeine Java-Themen 3
MJannek Java Überprüfen ob .exe-Datei bereits ausgeführt wird Allgemeine Java-Themen 2
Calli11 Was muss ich hier in die Main schreiben, damit das Programm ausgeführt wird? Allgemeine Java-Themen 4
Sachinbhatt Wie wird die Typumwandlung bei Mehrfachvererbung in Java implementiert? Allgemeine Java-Themen 3
Y MVVM wie wird Eventhandler tausch geregelt Allgemeine Java-Themen 4
berserkerdq2 run-methode eines Threads so programmieren, dass 30x die Sekunde etwas ausgeführt wird. Allgemeine Java-Themen 44
T ImageIcon wird nicht angezeigt Allgemeine Java-Themen 6
N Warum wird die For Schleife nicht betreten Allgemeine Java-Themen 4
N warum wird es doppelt ausgegeben Allgemeine Java-Themen 6
A code wird nicht ausgeführt Allgemeine Java-Themen 3
Y Warum wird das JLabel falsch verschoben? Allgemeine Java-Themen 1
T Schaltfläche wird nicht gefunden Allgemeine Java-Themen 4
N Eingabe wird immer als "false" ausgegeben Allgemeine Java-Themen 6
D Firebase retrieve data Problem, Child Element wird nicht angesprochen Allgemeine Java-Themen 0
M Frage-Antwortspiel wie Wer wird Millionär Allgemeine Java-Themen 1
Zrebna Gibt es eine Möglichkeit eine NPE zu vermeiden, wenn null returned wird? Allgemeine Java-Themen 3
R Warum wird mir in der Konsole das "Standard Array" ausgegeben? Allgemeine Java-Themen 2
C FileLock - Exception wird immer geworfen Allgemeine Java-Themen 4
R Was muss ich ändern, damit der Kreis links unten gezeichnet wird? Allgemeine Java-Themen 17
hello_autumn Java_Home geändert auf Java 13, trotzdem wird Java Version 8 angezeigt. Allgemeine Java-Themen 2
Thallius Char +1 wird int? Allgemeine Java-Themen 7
S Wenn eine Klasse zwei Interfaces mit derselben Methodensignatur implementiert: welche wird aufgerufen? Allgemeine Java-Themen 15
F Scrollbar wird nicht angezeigt Allgemeine Java-Themen 0
B Discord Bot - Funktion wird nicht aufgerufen Allgemeine Java-Themen 1
I Temp-Datei wird nicht gelöscht Allgemeine Java-Themen 12
S If-Menü wird doppelt ausgegben Allgemeine Java-Themen 4
P Variable wird in for - loop nicht richtig hochgezählt Allgemeine Java-Themen 11
S Wird bei den JREs 9, 10, 11+ ueberhaupt noch Bytecode ausgefuehrt..? Allgemeine Java-Themen 8
FRI3ND JFrame wird nicht angezeigt Allgemeine Java-Themen 3
T Plötzlich wird package nicht mehr gefunden Allgemeine Java-Themen 3
X Klassen File-Klasse wird als Directory markiert Allgemeine Java-Themen 8
S Datei wird nicht gefunden Thread.currentThread().getContextClassLoader().getResourceAsStream() Allgemeine Java-Themen 1
mrbig2017 Sleep wird ignoriert und der Thread wartet nicht Allgemeine Java-Themen 1
mrbig2017 Threads wait wird nicht durch notify beendet! Allgemeine Java-Themen 3
kodela Klassen Klassenvariable wird nicht gesetzt Allgemeine Java-Themen 23
M Was geschieht mit Java-Klasse, die aus ArrayList entfernt wird? Allgemeine Java-Themen 10
kodela Drücken der ALT-Taste wird nur bei jedem zweiten Mal erkannt Allgemeine Java-Themen 5
Arif Input/Output Serialisierung - Datei wird nicht erzeugt Allgemeine Java-Themen 3
D Cursor unsichtbar, wenn Kontextmenü aufgerufen wird Allgemeine Java-Themen 5
K Arbeitsspeicher wird langsam voll Allgemeine Java-Themen 6
The Pi Wie oft wird ein Buchstabe in einem Wort wiederholt? Allgemeine Java-Themen 16
N Datentypen If-Statement wird "übersprungen" Allgemeine Java-Themen 2
F Java Mail Problem: Authentifizierung wird nicht immer mitgeschickt Allgemeine Java-Themen 1
T Textarea text wird immer überschrieben Allgemeine Java-Themen 4
C Durch klicken von Button in GUI wird leeres Fenster geöffnet und nicht mein Spiel "Memory" Allgemeine Java-Themen 13
T Java wird nicht gefunden Allgemeine Java-Themen 32
Tacofan GIF-Bild wird "zerstört" Allgemeine Java-Themen 3
Z Exception wird nicht ausgelöst Allgemeine Java-Themen 2
Sin137 Interface Eingabe wird doppelt angezeigt Allgemeine Java-Themen 2
B Threads Timer wird immer schneller Allgemeine Java-Themen 6
N Maven ObjectMapper Error wenn das File gespeichert wird Allgemeine Java-Themen 0
G Methoden Aus einem Event, wo ich weiß, dass es ausgeführt werden wird, eine Get-Methode basteln Allgemeine Java-Themen 8
F Wert in Variable schreiben, wenn diese gerade genutzt wird Allgemeine Java-Themen 10
E Java wird beendet nach paar Sekunden Allgemeine Java-Themen 14
U Erkennen, ob PC benutzt wird Allgemeine Java-Themen 4
O Programm wird einfach "gekillt" Allgemeine Java-Themen 3
P Prüfen ob es Variable mit Namen gibt der als String übergeben wird Allgemeine Java-Themen 7
P Zwei ArrayLists: Ohne die eine überhaupt anzurühren, wird sie verändert Allgemeine Java-Themen 2
B Abfragenteil wird nicht aufgerufen Allgemeine Java-Themen 2
Todesbote JFileChooser im Vordergrund (*.jar wird mittels shell_exec in PHP aufgerufen) Allgemeine Java-Themen 1
T Sicherheitshinweis - Zertifikat wird angefordert Allgemeine Java-Themen 5
L SetBounds wird vor dem Konstruktorcode aufgerufen - Wenn Startleiste links Allgemeine Java-Themen 1
P "Overriden statische Methode" Statische Methode die vererbt wird Allgemeine Java-Themen 5
I CountDown wird durch JOptionPane unterbrochen Allgemeine Java-Themen 11
P Wird double und float auf jedem Computer gleich berechnet? Allgemeine Java-Themen 10
G Tabelle wird nicht richtig dargestellt Allgemeine Java-Themen 9
HarleyDavidson Threads ProgressMonitor wird nicht angezeigt! Allgemeine Java-Themen 6
J OOP Überwachen, ob ein Objekt erzeugt wird Allgemeine Java-Themen 9
S Byte Array welches in Laufzeit aufgelöst wird // Objekt Array Allgemeine Java-Themen 3
A Long variable wird negativ??? Allgemeine Java-Themen 1
J CSV Datei wird ungewollt umformatiert Allgemeine Java-Themen 5
T MEthodenauruf testen, wenn instanz erst erzeugt wird Allgemeine Java-Themen 0
gamebreiti Swing JLabel wird nicht angezeigt Allgemeine Java-Themen 4
I Java Applet wird immer blockiert Allgemeine Java-Themen 3
E Java Editor Klasse wird nicht weiter ausgeführt Allgemeine Java-Themen 4
S Java Applet wird dauerhaft blockiert Allgemeine Java-Themen 1
I Datei wird nicht richtig gelöscht Allgemeine Java-Themen 7
K Methoden Objekt wird nicht erkannt Allgemeine Java-Themen 11
D Input/Output Datei wird lokal aber nicht vom Webserver ausgelesen... Allgemeine Java-Themen 2
F Nach Export wird PDF Datei nicht mehr gefunden Allgemeine Java-Themen 0
L Prüfen, ob Programm über 32bit oder 64bit Java ausgeführt wird Allgemeine Java-Themen 4
D ActionListener wird mit jedem Mal öfter aufgerufen Allgemeine Java-Themen 2
C System.in erhält Input von Tastatur. wo wird das festgelegt? Allgemeine Java-Themen 4
I Projekt wird nicht erstellt Allgemeine Java-Themen 2
T WeakReference/PhantomReference: Mitbekommen WELCHES Objekt nun GC'ed wird Allgemeine Java-Themen 2
A Threads Log4J Logger wird "überschrieben" Allgemeine Java-Themen 3
P Check, welche Java Version installiert bevor ein Programm ausgeführt wird. Allgemeine Java-Themen 12
J batch datei wird nicht aufgerufen Allgemeine Java-Themen 11
M Datei wird nicht vollständig geschrieben (FileOutputStream, OutputStreamWriter, Encoding) Allgemeine Java-Themen 6
P OSGi - Bundle-Methode wird nicht aufgerufen Allgemeine Java-Themen 3
S Antlr Grammatik übersetzt ohne Fehler, dennoch wird Zahl nicht als Eingabe erkannt Allgemeine Java-Themen 4
T Variablen Variable wird als nicht genutzt angezeigt Allgemeine Java-Themen 8
J Slideshow wird im IE überblendet Allgemeine Java-Themen 4
O Socket Object wird scheinbar falsch empfangen Allgemeine Java-Themen 6

Ähnliche Java Themen

Neue Themen


Oben