Seite 1 von 1

Rechenfehler

Verfasst: Freitag 19. Februar 2010, 11:49
von min
Hallo
neulich schreib ich ein skript mit Python in dem bestimmte Ergebnisse gerundet werden. eines dieser Ergebnisse war eine Simple Rechnung:

Code: Alles auswählen

int((8.1-8)*10)
Man sieht sofort, dass in der Klammer 0.1 rauskommt also nach dem Runden, bzw. wegstreichen der nachkommastellen, 1 rauskommen sollte. erstaunlicher weise kommt aber 0 raus. nach nachprüfung ist mir aufgefallen, dass Python als Ergebniss von "8.1-8" die Zahl "0.09999999999999964" herausbekommt. Kann man diesen Fehler beheben?
Nebenbei ich habe es auch auf folgende Art probiert:

Code: Alles auswählen

int((-8+8.1)*10)
oder

Code: Alles auswählen

int((8.1-8.0)*10)
Es geht nur auf diese Weise. Die kann ich bei mir aber nur schlecht anwenden:

Code: Alles auswählen

int(8.1*10-8*10)

Verfasst: Freitag 19. Februar 2010, 11:55
von BlackJack
@min: Das ist kein Python-Problem, sondern generell eines mit Gleitpunktzahlen. Kannst Du denn an der Stelle runden, oder ist es sonst wichtig, dass Nachkommastellen einfach abgeschnitten werden? Sonst würde ich einfach sagen: `round()` vor dem `int()` verwenden!?

Verfasst: Freitag 19. Februar 2010, 11:58
von CM

Code: Alles auswählen

round((8.1-8)*10)
Schau Dir mal help(int) und help(round) an, dann weisst Du wieso. Ggf. kannst Du ja noch int() auf die Rundung anwenden, wenn Du Integer brauchst.

edit: Viel zu langsam ...

Verfasst: Freitag 19. Februar 2010, 11:58
von Dav1d

Code: Alles auswählen

>>> round((8.1-8)*10, 1)
1.0
Mit round gehts

oder mit Decimal

Code: Alles auswählen

>>> from decimal import Decimal
>>> x = Decimal('8.1')
>>> (x-8)*10
Decimal('1.0')
Das Problem ist der Floatingpoint

//Edit nur wweil ich noch nach dem Artikel gesucht hab, in ich mal wieder der Letzte

Verfasst: Freitag 19. Februar 2010, 12:01
von min
Danke für die schnelle Antwort. round kann ich leider nicht davor verwenden. Aber dann such ich nach einer anderen Möglichkeit.

Verfasst: Freitag 19. Februar 2010, 12:03
von Dav1d
[mod]Decimal[/mod]!

Beim Decimal-Modul kann man auch die genauigkeit einstellen, ich glaub die ist bei 28 "Zahlen" als Std.

Verfasst: Freitag 19. Februar 2010, 12:17
von min
Die letzte Nachricht hat interesse in mir geweckt. Kann man die Genauigkeit von Ergebnissen allgemein beeinflussen. Hier mal eine Rechnung.

Code: Alles auswählen

ma.pow(c, n)%16
Meine Sorge ist, dass bei der Rechnung c^n die Ungenauigkeit zu groß ist.

Verfasst: Freitag 19. Februar 2010, 12:37
von Dav1d
Ohne Modulo dafür mit Float

Code: Alles auswählen

>>> from decimal import Context, Decimal
>>> con = Context(prec=100)
>>> con.power(Decimal('123.123432423'), Decimal('234234'))
Decimal('7.359572003390624900250649596149288882706325929782898301264262930315127844951171911253813989216723952E+489628')
Mit Modulo und Integer

Code: Alles auswählen

>>> con.power(Decimal('123123'), Decimal('345623'), Decimal('16'))
Decimal('11')

Verfasst: Freitag 19. Februar 2010, 13:44
von min
Danke das reicht vollkommen. :D

Verfasst: Freitag 19. Februar 2010, 13:48
von numerix
CM hat geschrieben:Ggf. kannst Du ja noch int() auf die Rundung anwenden, wenn Du Integer brauchst.
Ab Python 3 nicht mehr nötig.

min hat geschrieben:Danke für die schnelle Antwort. round kann ich leider nicht davor verwenden.
Wieso nicht?
min hat geschrieben:Meine Sorge ist, dass bei der Rechnung c^n die Ungenauigkeit zu groß ist.
Das hängt davon ab, mit welcher Art von Zahlen du es zu tun hast. Dein Beispiel "mod 16" deutet auf Ganzzahlarithmetik. Da brauchst du dir dann keine Gedanken zu machen. Allerdings solltest aus Gründen der Performance zur Berechnung von modularen Potenzen den dritten, optionalen Parameter von pow() verwenden.

Verfasst: Freitag 19. Februar 2010, 16:42
von min
Ich weiß leider nichts von einem dritten Parameter. Könntest du mich da aufklären? wäre sehr dankbar

Verfasst: Freitag 19. Februar 2010, 17:03
von Klip

Verfasst: Freitag 19. Februar 2010, 17:04
von numerix

Code: Alles auswählen

>>> pow(3,19,7)
3
>>> pow(3,19) % 7
3
Die Ergebnisse sind äquivalent, die Art der Berechnung nicht.
Die 2. Variante ist für große Exponenten nicht performant, weil zunächst eine sehr große Potenz berechnet wird, auf die dann der Modulo-Operator angewendet wird.
Die 1. Variante berechnet das Ergebnis mittels binärer Exponentiation - das ist erhebliche performanter.

Verfasst: Freitag 19. Februar 2010, 17:34
von Dav1d
Der selbe 3. Parameter wie bei

Code: Alles auswählen

con.power
siehe Decimal