Ints und Floats - so verschieden..?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
Don Polettone
User
Beiträge: 115
Registriert: Dienstag 23. November 2010, 20:26
Wohnort: Schweiz

Hallo werte Kollegen und Kolleginnen Schlangenbeschwörer :-)

Ich mach's kurz. Ich bin blutiger Anfänger und etwas geht da nicht in meinen Kopf:

a = 0

while a != 10:
a += 1
print a
else:
print 'a ist jetzt 10'

soweit, so gut - das funzt sogar glaub' ich. Aber warum zum was-auch-immer geht das nicht mit Floats..?!

a = 0

while a != 10:
a += 0.1
print a
else:
print 'a ist jetzt 10'

dies gibt eine Endlosschleife und der rechnet immer 0.1 dazu und gibt den Wert aus, bis... ...wohl bis mal der Strom ausfällt oder das OS streikt.

WARUM??? Es ist auch vollkommen egal, ob ich alle Werte bereits im Vorfeld als Floats definiere (also 0.0 und 10.0) - es geht auch dann nicht.

Auch wenn's Euch banal erscheint: Ich schnall's einfach nicht und wäre echt froh, wenn mich jemand ein wenig erleuchten könnte...

Im Vorfeld merci 1000,


Thomas
Benutzeravatar
DaMutz
User
Beiträge: 202
Registriert: Freitag 31. Oktober 2008, 17:25

Willkommen im Forum!

Das Problem mit floats ist, dass sie nicht eine beliebige Genauigkeit haben. Siehe zum Beispiel dieses Beispiel:

Code: Alles auswählen

In [11]: 10 - 9.9
Out[11]: 0.099999999999999645
wenn du jetzt diese Zahl auf Gleichheit prüfen würdest, wäre es nicht 0.1

Code: Alles auswählen

In [12]: 10 - 9.9 == 0.1
Out[12]: False
Prüfe darum immer einen Bereich oder grösser als (oder kleiner als).
Benutzeravatar
Don Polettone
User
Beiträge: 115
Registriert: Dienstag 23. November 2010, 20:26
Wohnort: Schweiz

Hey besten Dank für die Antwort erst mal :-)

Aber mit Verlaub:

Wie soll ich in einer Programmiersprache, welche nicht mal 10 - 0.1 so rechnen kann, dass das Ergebnis 9.9 beträgt, ein Programm schreiben..? Das ist nicht Euer Ernst, oder..? Ich meine, jeder Programmierer muss doch ständig Sachen errechnen lassen - und diese sind wohl in den allermeisten Fällen um ein Tausendfaches komplizierter als diese simple Rechnung, nicht? Das Zeug muss doch stimmen, sonst kann man ja nicht programmieren?? Ich seh's nicht mehr...

Was tut Ihr denn, wenn Ihr diese Rechnung im Programm haben MÜSST? Muss man immer angeben, auf wie viele Stellen gerundet werden soll?

erschüttert, desorientiert und der Verzweiflung nahe:


Thomas
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

Es gibt das modul Decimal.

Das Problem liegt am Binärsystem, nicht an der Programmiersprache!
[url=http://wiki.python-forum.de/PEP%208%20%28%C3%9Cbersetzung%29]PEP 8[/url] - Quak!
[url=http://tutorial.pocoo.org/index.html]Tutorial in Deutsch[/url]
Benutzeravatar
Don Polettone
User
Beiträge: 115
Registriert: Dienstag 23. November 2010, 20:26
Wohnort: Schweiz

wow, krass...

danke :mrgreen:
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

Versuch mal 1/3 genau zu schreiben. Da bekommst du auch nur 0,33333...
[url=http://wiki.python-forum.de/PEP%208%20%28%C3%9Cbersetzung%29]PEP 8[/url] - Quak!
[url=http://tutorial.pocoo.org/index.html]Tutorial in Deutsch[/url]
BlackJack

@Henry Jones Jr.: Das hat nicht viel mit der Programmiersprache zu tun, sondern ist halt Grundsätzlich ein Problem mit Fliesskommazahlen. Die haben a) keine beliebige Genauigkeit, und werden b) in einem Zahlensystem (binär) gespeichert bei dem andere "Dezimalbrüche" nicht endlich genau beschrieben werden können, als im Dezimalsystem. 0.1 lässt sich zum Beispiel nicht genau speichern, das Ergebnis von 1/3 dagegen schon.

Man kann kompliziertere Sachen berechnen, aber eben nicht genau und was eben richtig problematisch wird, sind genaue Vergleiche. Die darf man halt nicht machen, sonst passieren solche Sachen wie Deine Endlosschleife. Das ist halt so. Und in den letzten paar Jahrzehnten haben die Leute es ja auch geschafft damit zu programmieren.

Wenn ich so eine Schleife haben "muss", dann kann ich das halt nicht durch wiederholte Addition machen, wo bei jedem Additionsschritt wieder etwas mehr Ungenauigkeit in das Zwischenergebnis kommt. Nochmal was um Dich zu "erschrecken":

0.1 wird etwas grösser gespeichert als eine tatsächliche 0.1:

Code: Alles auswählen

In [171]: 0.1
Out[171]: 0.10000000000000001
Wenn man jetzt 10 dieser Zahlen aufaddiert, könnte man ja auf die Idee kommen, das Ergebnis ist grösser als 1. Überraschung:

Code: Alles auswählen

In [172]: sum([0.1] * 10)
Out[172]: 0.99999999999999989
Und Runden nützt nichts, den 0.1 kann nun einmal intern nicht genau dargestellt werden. Jedenfalls nicht mit dem Fliesskommaformat, welches der Prozessor versteht und mit dem er schnell rechnen kann.
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

Benutzeravatar
Don Polettone
User
Beiträge: 115
Registriert: Dienstag 23. November 2010, 20:26
Wohnort: Schweiz

ist ja hammerhart!

Vielen Dank. Ich hatte ja keine Ahnung...

willkommen in der Matrix :o
Ich code, also bin ich.
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Henry Jones Jr. hat geschrieben:ist ja hammerhart!
Wenn du noch mehr Hintergrund haben möchtest, dann lies mal in Wikipedia den Artikel über Gleitkommazahlen. Der erste Satz sagt eigentlich schon alles: "Eine Gleitkommazahl (auch Gleitpunktzahl oder Fließkommazahl; engl. floating point number) ist eine approximative Darstellung einer reellen Zahl". Es ist also auf jeden Fall nur eine Näherung. Ganz böse sind dann solche Dinge wie die Ungültigkeit des Assoziativgesetzes.

Das bereits erwähnte Decimal-Modul schafft in Python Abhilfe. Hier sind die Berechnungen allerdings nicht mehr in Hardware (Prozessor) gegossen, so dass du dir durch die erhöhte Genauigkeit Performanceeinbußen einhandelst.
Antworten