0.7+0.2

  • Themenstarter Themenstarter Guest
  • Beginndatum Beginndatum
Status
Nicht offen für weitere Antworten.
G

Guest

Gast
hi mal ne frage :
wieso kommt wenn ich in einen java programm 0.7+0.2 rechne 0.8999999999999999 raus?
was kann ich unternehmen damit ich das korrekte ergebnis erhalte ?
 
runden
btw: es gibt einige threads zu dem thema wo das ausführlicher erläutert wird: suchfunktion
 
Hm da hab ich aber mal nen Test gemacht (hab ich den eigentlich schonmal gepostet? kA):

Java

Code:
public class FloatingPointTest
{
	public static void main (String[] args)
    {
    	for (double d = 0; d < 5; d += .2){
    		System.out.println (d);
    	}
    }
}
0.0
0.2
0.4
0.6000000000000001
0.8
1.0
1.2
1.4
1.5999999999999999
1.7999999999999998
1.9999999999999998
2.1999999999999997
2.4
2.6
2.8000000000000003
3.0000000000000004
3.2000000000000006
3.400000000000001
3.600000000000001
3.800000000000001
4.000000000000001
4.200000000000001
4.400000000000001
4.600000000000001
4.800000000000002

C#

Code:
using System;

namespace MyTest
{
	public class FloatingPointTest
	{
		public static void Main (string[] args)
		{
			for (double d = 0; d < 5; d += .2){
				Console.Out.WriteLine (d);
			}
		}
	}
}
0
0,2
0,4
0,6
0,8
1
1,2
1,4
1,6
1,8
2
2,2
2,4
2,6
2,8
3
3,2
3,4
3,6
3,8
4
4,2
4,4
4,6
4,8
 
Ich könnte mir gut vorstellen, dass die C#-Print-Methode noch ein bisschen rundet.

Wildcard hat schon recht, die Fliesskommazahlen können einige "einfache" Dezimalzahlen schlicht nicht darstellen.
 
ja weil c, c# etc. automatisch runden oder so.

edit: mist 1 sekunde später
 
Nöö, es ist sicherlich eine andere interne Darstellung von Dezimalzahlen.
Es gibt Sprachen, bei denen dies "normal" ist, dass sie sehr genau bei
Fliesskommaoperationen sind.
z.B. Clarion: Dezimal mit einer Genauigkeit von 31 Stellen vor und nach
dem Komma. (Intern als BCD)
 
Nöö, es ist sicherlich eine andere interne Darstellung von Dezimalzahlen.
Es gibt Sprachen, bei denen dies "normal" ist, dass sie sehr genau bei
Fliesskommaoperationen sind.
Jede Sprache die sich an die IEEE 754 hält (was meines wissens fast jede 'gängige' Sprache' einschließt) kann Zahlen wie 0.1 nicht richtig als Fließkommazahl darstellen(eigentlich überhauptnicht rein binär).
Daher schließe ich mich Roar und Beni an, und sage das ist gerundet...
 
Die interne Zahlendarstellung ist in C#/C/Java definitiv die gleiche (jedenfalls solange man in Java nicht strictmath benutzt). Allerdings habe ich auch den Eindruck, daß die Standardlibraries anderer Sprachen "geschickter" runden.
Daß dort aber auch nur mit Wasser gekocht wird, kann man leicht zeigen:
0.2*0.2-0.04 sollte 0 ergeben, ergibt aber auch in C++ in double gerechnet 6.93889390391e-018.
 
@Illus Test:

C#

Code:
using System;

namespace MyTest
{
	public class FloatingPointTest
	{
		public static void Main (string[] args)
		{
			double i = 0;
			for (double d = 0; d < 5; d += 0.2){

				double dd  = d * 10;
				bool b = dd == i;
				Console.Out.WriteLine (dd + " == " + i + ": " + b);
				i+=2;
			}
			Console.Out.WriteLine (0.2*0.2-0.04 );
		} 
	}
}
0 == 0: True
2 == 2: True
4 == 4: True
6 == 6: False
8 == 8: True
10 == 10: True
12 == 12: True
14 == 14: True
16 == 16: False
18 == 18: True
20 == 20: False
22 == 22: False
24 == 24: True
26 == 26: True
28 == 28: False
30 == 30: False
32 == 32: False
34 == 34: False
36 == 36: False
38 == 38: False
40 == 40: False
42 == 42: False
44 == 44: False
46 == 46: False
48 == 48: False
6,93889390390723E-18



java:
Code:
public class FloatingPointTest
{
	public static void main (String[] args)
    {
		double i = 0;
        for (double d = 0; d < 5; d += 0.2){

           double dd  = d * 10;
           boolean b = dd == i;
           System.out.println (dd + " == " + i + ": " + b);
           i+=2;
        }
		System.out.println  (0.2*0.2-0.04 ); 

	}
}

0.0 == 0.0: true
2.0 == 2.0: true
4.0 == 4.0: true
6.000000000000001 == 6.0: false
8.0 == 8.0: true
10.0 == 10.0: true
12.0 == 12.0: true
14.0 == 14.0: true
15.999999999999998 == 16.0: false
18.0 == 18.0: true
19.999999999999996 == 20.0: false
21.999999999999996 == 22.0: false
24.0 == 24.0: true
26.0 == 26.0: true
28.000000000000004 == 28.0: false
30.000000000000004 == 30.0: false
32.00000000000001 == 32.0: false
34.00000000000001 == 34.0: false
36.00000000000001 == 36.0: false
38.000000000000014 == 38.0: false
40.00000000000001 == 40.0: false
42.000000000000014 == 42.0: false
44.000000000000014 == 44.0: false
46.000000000000014 == 46.0: false
48.000000000000014 == 48.0: false
6.938893903907228E-18
 
double werte kann man nicht auf gleichheit prüfen nur auf
< oder > , und sich einer beliebigen genauigkeit einigen
z.b ob es 0 ist
while (!(doubleWert > 1E-6))
.
.
.
und wenn es dann halt kleiner ist hat man 0
 
Klar kann man, man sollte nur drauf achten was man damit vorher gemacht hat. Evtl. vor der Prüfung runden.
Oder was meinst?
 
man SOLL nicht auf = prüfen

=> in .NET gibts da ne eigene Konstante (Epsilon)

=> in Java Double.MIN_VALUE
 
Wildcard hat gesagt.:
Wildcard hat gesagt.:
Dann erklär mir doch mal wie du z.B. 0.1 korrekt als Fließkommazahl darstellen willst?
Illuvatar hat gesagt.:
Naja, andere Sprachen schaffen das auch :?
Nicht wirklich, das ist ein Problem der Fließkommazahlen und die sind Standard...

Und noch ein Auszug aus einem Buch:

VB 6 in 21 Tagen hat gesagt.:
Strings, Boolesche Werte, Währungsdaten, Datumswerte, Zeitwerte und die Integer-Datentypen (Byte, Integer und Long) können auf Gleichheit miteinander verglichen werden. Versuchen Sie jedoch nicht, zwei Werte mit einfacher oder mit doppelter Genauigkeit zu vergleichen. Aufgrund der Methode, wie Visual Basic Daten mit einer bestimmten Genauigkeit speichert, erscheinen zwei Werte mit einfacher Genauigkeit möglicherweise ungleich, weil Visual Basic intern eine Rundung für solche Werte vornimmt. Wenn Sie zwei Variablen mit gleicher Genauigkeit vergleichen möchten, subtrahieren Sie sie und vergleichen die Differenz, um zu prüfen, ob sie annähernd gleich sind. Diese Codierung ist mühsam, vermeiden Sie sie also, wo immer Sie können.
 
Btw.: C Code, wegen eurer "vorformatieren C#" Ausgabe:

Code:
	for (double d = 0; d < 5; d += .2){
          printf("%lf\n",d);
       }

C hat gesagt.:
0.000000
0.200000
0.400000
0.600000
0.800000
1.000000
1.200000
1.400000
1.600000
1.800000
2.000000
2.200000
2.400000
2.600000
2.800000
3.000000
3.200000
3.400000
3.600000
3.800000
4.000000
4.200000
4.400000
4.600000
4.800000


Nachtrag:

Code:
int main(int argc, char* argv[])
{
	
	double i = 0;
	for (double d = 0; d < 5; d += 0.2)
	{
      double dd  = d * 10;
      bool b = dd == i;
      printf("%lf == %lf : %d\n",dd,i,b);
      i+=2;
    }
    printf("\n\n%lf",0.2*0.2-0.04 ); 

	return 0;
}

C hat gesagt.:
0.000000 == 0.000000 : 1
2.000000 == 2.000000 : 1
4.000000 == 4.000000 : 1
6.000000 == 6.000000 : 0
8.000000 == 8.000000 : 1
10.000000 == 10.000000 : 1
12.000000 == 12.000000 : 1
14.000000 == 14.000000 : 1
16.000000 == 16.000000 : 0
18.000000 == 18.000000 : 1
20.000000 == 20.000000 : 0
22.000000 == 22.000000 : 0
24.000000 == 24.000000 : 1
26.000000 == 26.000000 : 1
28.000000 == 28.000000 : 0
30.000000 == 30.000000 : 0
32.000000 == 32.000000 : 0
34.000000 == 34.000000 : 0
36.000000 == 36.000000 : 0
38.000000 == 38.000000 : 0
40.000000 == 40.000000 : 0
42.000000 == 42.000000 : 0
44.000000 == 44.000000 : 0
46.000000 == 46.000000 : 0
48.000000 == 48.000000 : 0


0.000000

Nachtrag2: Irgendwie sind die boolschen Vergleiche bei C,C# und Java gleich 🙂

Nur die Rechnung kommt in C richtig raus ^^
 
Ob 0,999999999 oder 1, das ist egal, weil es ein und dasselbe sind.

1/9 = 0,1111111111111111111111111

0,11111111111 * 9 = 0,999999999999999

1/9 * 9 = 1 (kürzt sich raus)

Ergo => 0,9999999999999999 und 1 sind dasselbe.
 
PI = genau 3 😀


Naja, für mich sollten das nicht dasselbe sein, wwweil was ist wenn du wirklich mal 0,9999999 haben willst und net 1 ??
 
sky80 hat gesagt.:
thE_29 hat gesagt.:
Naja, für mich sollten das nicht dasselbe sein, wwweil was ist wenn du wirklich mal 0,9999999 haben willst und net 1 ??
Mathematisch betrachtet ist es nun aber so, dass es das gleiche ist!

0,999999999999999 entspricht nunmal 9/9 und ist somit 1!

Sorry, aber die Mathematik kann ich nicht so schnell ändern ;-)
Jo, genau. Man kann es auch mit Worten erklären. Wenn 0,99999999 unendlich viele 9er hat, dann ist die Differenz zwischen 0,999999999 und 1 unendlich klein => ein und dasselbe.

Liebe Grüße
Reality
 
Jo, nur muss man auch sagen das

0,111 != 1/9 ist!

Sondern

0,111° = 1/9 (wobei ° für peridoisch ist)

Da ist halt wieder das Problem, wenn man halt wirklich mit so einer Zahl rechnet (die nicht periodisch ist, sondern einfach nur so aussieht)
 
Der Thread ist zwar schon etwas älter, aber ich wollt noch was dazu sagen.
Und zwar gibt es natürlich in java auch die möglichkeit "genau" zu rechnen, und zwar mit dem package java.math, dort finden sich die Klassen BigDecimal , BigInteger und MathContext damit gibt es die Möglichkeit so genau zu rechnen wie man will, man hat nämlich die völlige Kontrolle darüber wie gerundet wird. Wie genau das funktioniert weiss ich leider auch nicht mehr, aber steht alles in der API. Ist sehr interessant.
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben