PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : c++: float hochzählen wird ungenau??



stefan-tiger
01-10-2003, 18:58
hallo,

ich lass per c++ eine float zahl um 0,01 in einer schleife hochzählen.
nach einer weile wird aus a,a1 a,aa999999. warum?

folgender code:

main.cpp



#include <iostream>

int main(void)
{
std::cout << "Mein Programm" << std::endl;

float x;
float y;
x = 0.00;

do
{
y=2*x-3;
std::cout << "x=" << x << " y=" << y << std::endl;
x=x+0.01;
}
while(x < 1.00);

};



ergibt folgende ausgabe:

bash-2.05b$ g++ -o run.bin main.cpp && ./run.bin
Mein Programm
x=0 y=-3
x=0.01 y=-2.98
x=0.02 y=-2.96
x=0.03 y=-2.94
x=0.04 y=-2.92
x=0.05 y=-2.9
x=0.06 y=-2.88
x=0.07 y=-2.86
x=0.08 y=-2.84
x=0.09 y=-2.82
x=0.1 y=-2.8
x=0.11 y=-2.78
x=0.12 y=-2.76
x=0.13 y=-2.74
x=0.14 y=-2.72
x=0.15 y=-2.7
x=0.16 y=-2.68
x=0.17 y=-2.66
x=0.18 y=-2.64
x=0.19 y=-2.62
x=0.2 y=-2.6
x=0.21 y=-2.58
x=0.22 y=-2.56
x=0.23 y=-2.54
x=0.24 y=-2.52
x=0.25 y=-2.5
x=0.26 y=-2.48
x=0.27 y=-2.46
x=0.28 y=-2.44
x=0.29 y=-2.42
x=0.3 y=-2.4
x=0.31 y=-2.38
x=0.32 y=-2.36
x=0.33 y=-2.34
x=0.34 y=-2.32
x=0.35 y=-2.3
x=0.36 y=-2.28
x=0.37 y=-2.26
x=0.38 y=-2.24
x=0.39 y=-2.22
x=0.4 y=-2.2
x=0.41 y=-2.18
x=0.42 y=-2.16
x=0.43 y=-2.14
x=0.44 y=-2.12
x=0.45 y=-2.1
x=0.46 y=-2.08
x=0.47 y=-2.06
x=0.48 y=-2.04
x=0.49 y=-2.02
x=0.5 y=-2
x=0.51 y=-1.98
x=0.52 y=-1.96
x=0.53 y=-1.94
x=0.54 y=-1.92
x=0.55 y=-1.9
x=0.56 y=-1.88
x=0.57 y=-1.86
x=0.58 y=-1.84
x=0.59 y=-1.82
x=0.6 y=-1.8
x=0.61 y=-1.78
x=0.62 y=-1.76
x=0.63 y=-1.74
x=0.64 y=-1.72
x=0.65 y=-1.7
x=0.66 y=-1.68
x=0.67 y=-1.66
x=0.68 y=-1.64
x=0.69 y=-1.62
x=0.7 y=-1.6
x=0.71 y=-1.58
x=0.72 y=-1.56
x=0.73 y=-1.54
x=0.74 y=-1.52
x=0.75 y=-1.5
x=0.76 y=-1.48
x=0.77 y=-1.46
x=0.78 y=-1.44
x=0.79 y=-1.42
x=0.8 y=-1.4
x=0.81 y=-1.38
x=0.82 y=-1.36
x=0.83 y=-1.34
x=0.839999 y=-1.32
x=0.849999 y=-1.3
x=0.859999 y=-1.28
x=0.869999 y=-1.26
x=0.879999 y=-1.24
x=0.889999 y=-1.22
x=0.899999 y=-1.2
x=0.909999 y=-1.18
x=0.919999 y=-1.16
x=0.929999 y=-1.14
x=0.939999 y=-1.12
x=0.949999 y=-1.1
x=0.959999 y=-1.08
x=0.969999 y=-1.06
x=0.979999 y=-1.04
x=0.989999 y=-1.02
x=0.999999 y=-1

stefan-tiger
01-10-2003, 19:10
mit double gehts.

bin wohl etwas müde!?

wraith
01-10-2003, 19:17
Original geschrieben von stefan-tiger
mit double gehts.

Nein,nicht wirklich.
Fließkommazahlen sind nicht exakt,viele Zahlen lassen sich nur als Näherungen darstellen.
Pack' vor dein couts in der Schleife noch ein
std::cout.precision(50);
Dann werden mehr Stellen angezeigt.

stefan-tiger
01-10-2003, 19:52
Original geschrieben von wraith
Nein,nicht wirklich.
Fließkommazahlen sind nicht exakt,viele Zahlen lassen sich nur als Näherungen darstellen.
Pack' vor dein couts in der Schleife noch ein
std::cout.precision(50);
Dann werden mehr Stellen angezeigt.

wie nicht exakt?

ist 0.01 nicht exakt?

und 0.83 + 0.01 sollte exakt 0.84 sein.

wieso ist das nicht exakt.

ich könnte ja meine schleife mit ganzen zahlen machen und dann die ergebnisse durch 100 teilen! aber das wär doch unsinn wenn man in 0.01er schritten zählen könnte.

gruß und danke

EDIT: und mit double gehts doch, zumindest wirds richtig ausgegeben :-)

wraith
01-10-2003, 20:09
Original geschrieben von stefan-tiger
wie nicht exakt?

ist 0.01 nicht exakt?

und 0.83 + 0.01 sollte exakt 0.84 sein.

wieso ist das nicht exakt.


double,float usw. haben nur eine begrenzte Anzahl von Bits,also kann nur eine begrenzte Auswahl von Zahlen dargestellt werden.
Hier wird das Thema erschöpfend behandelt
What Every Computer Scientist Should Know About Floating-Point Arithmetic (http://cch.loria.fr/documentation/IEEE754/ACM/goldberg.pdf)




und mit double gehts doch, zumindest wirds richtig ausgegeben :-)
Wenn ich bei mir davor precision(50) davor setze bekomme ich zb. solche Ausgaben:
0.11999999999999999
Wenn du die precision auf dem Standardwert läßt,dann wird gerundet,und daher glaubst du,daß der Wert exakt ist,das ist er aber nicht.

anda_skoa
02-10-2003, 09:48
Wenn du mit einer beschränken Anzahl Nachkommastellen arbeiten kannst, zB bei Geldbeträgen, dann kann man einen Festkomma wert nehmen und nur bei der Ausgabe entsprechend skalieren.

Also statt 12.34 würde man dann mit dem Wert 1234 rechnen und bei der Ausgabe das Ergebnis durch 100 dividieren.

Ciao,
_

Boron
02-10-2003, 14:07
DAs erste was man mir and der FH Konstanz beigebracht hat war: "Rechnet nie mit float oder double."

Eher früher als später werden die Ergebnisse falsch und somit unbrauchbar.