komischer for-loop ...

sammy2ooo

voll Tohuwabohu
kann mir jemand dieses Phaenomen erklaeren? Was stimmt da mit 0.0 nicht???? :ugly:

g++ --version g++ (GCC) 4.1.1 (Gentoo 4.1.1-r3)

Code:
for (float i = 2.5; i >= -0.1; i-=0.1) {
                cout << i << endl;
        }

2.5
2.4
2.3
2.2
2.1
2
1.9
1.8
1.7
1.6
1.5
1.4
1.3
1.2
1.1
1
0.9
0.8
0.7
0.6
0.5
0.4
0.3
0.2
0.1
1.35601e-07
-0.0999999

Code:
for (double i = 2.5; i >= -0.1; i-=0.1) {
                cout << i << endl;
        }

2.5
2.4
2.3
2.2
2.1
2
1.9
1.8
1.7
1.6
1.5
1.4
1.3
1.2
1.1
1
0.9
0.8
0.7
0.6
0.5
0.4
0.3
0.2
0.1
-1.08247e-15
 
Bei Gleitpunktzahlen gemäß IEEE wird nur die Mantisse gespeichert, während der Vorkommateil immer 1 ist.
 
okay, danke fuer deine Antwort. Aber wie kann ich das nun umgehen? Ich moechte trotzdem eine schoene for-schleife haben.
 
AFAIK geht das z.B. mit der GNU Multi-Precision Library. Einfach mal nach "Arbitrary Precision Arithmetic" oder "Bignum" suchen, zu diesem Zweck gibt es einige Bibliotheken.
 
Wenn ich mich recht erinnere können Gleitkommatypen auch die 0 in einer Sonderform (alle Bits 0) darstellen. Das klappt aber nur, wenn keine Rundungsfehler auftreten. Dafür sind natürlich Intervalle, die binär gut darstellbar sind besser geeignet. Z.B. 0.5, 0.25, 0.125 usw. Auch nicht getestet, aber ich würde erwarten, dass es damit keine Probleme gibt. Also versuch einfach mal i -= 0.125 nur so zum Testen.
 
mit i -= 0.125 klappt das. Allerdings ist mir das nicht klar. Warum kann ich nicht einfach 0.1 - 0.1 rechnen und erhalte dann 0.0 ??? :confused:

ein cout << 0.1 - 0.1 << endl; ergibt ja auch 0
 
mit i -= 0.125 klappt das. Allerdings ist mir das nicht klar. Warum kann ich nicht einfach 0.1 - 0.1 rechnen und erhalte dann 0.0 ??? :confused:

ein cout << 0.1 - 0.1 << endl; ergibt ja auch 0

ist bei dir irgendwo eine universität oder fachhochschule, an der irgendein informatik-studiengang gelehrt wird?
wenn ja, geh doch mal in die vorlesung "Grundlagen der Informatik I" oder "Nummerische Mathematik" oder ähnliches, da wird sowas groß und breit erklärt.

ansonsten: es wurden schon genügend links gepostet.

auf bald
oenone
 
mit i -= 0.125 klappt das. Allerdings ist mir das nicht klar. Warum kann ich nicht einfach 0.1 - 0.1 rechnen und erhalte dann 0.0 ??? :confused:

ein cout << 0.1 - 0.1 << endl; ergibt ja auch 0

0.125 kannst du binär 0.001 darstellen. In der FP Darstellung läuft das auf 1.000... * 2^-3 hinaus. Das ist sehr simpel und hat zur Folge, dass nicht gerundet wird. 0.1 hingegen wäre so etwas wie 0.000110011... usw. Das liefe dann auf 1.10011... * 2^-4 hinaus. Das Problem ist, dass die 0.1 (Dezimal) in Binärdarstellung eine periodische Zahl ist (0011 setzt sich unendlich fort). Damit ist eine genaue Darstellung auch nur mit unendlich großem Speicher möglich. In der Realität sind das aber weniger als 32 bit (man braucht auch Speicher für den Exponenten). Da passt eine unendlich lange Zahl einfach nicht rein, also kann damit auch nicht genau gerechnet werden und es kommt zwangsläufig zu Fehlern.
 
du kannst ja auch im Notfall deinen eigenen Datentyp mit
beliebiger Genauigkeit und Grösse progen (natürlich nur so beliebig wie deine RAM gross sind :) )

Code:
class big {
  //...
  std::vector<short> speicher_ziffer;
  //...
};

Mit Gleitkommazahlen muss du halt etwas basteln.

Gruss,
Gg
 
Zurück
Oben