Rechenfehler

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
min
User
Beiträge: 37
Registriert: Dienstag 22. Dezember 2009, 22:25

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)
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!?
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

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 ...
Zuletzt geändert von CM am Freitag 19. Februar 2010, 11:58, insgesamt 1-mal geändert.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

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
the more they change the more they stay the same
min
User
Beiträge: 37
Registriert: Dienstag 22. Dezember 2009, 22:25

Danke für die schnelle Antwort. round kann ich leider nicht davor verwenden. Aber dann such ich nach einer anderen Möglichkeit.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

[mod]Decimal[/mod]!

Beim Decimal-Modul kann man auch die genauigkeit einstellen, ich glaub die ist bei 28 "Zahlen" als Std.
the more they change the more they stay the same
min
User
Beiträge: 37
Registriert: Dienstag 22. Dezember 2009, 22:25

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.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

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')
the more they change the more they stay the same
min
User
Beiträge: 37
Registriert: Dienstag 22. Dezember 2009, 22:25

Danke das reicht vollkommen. :D
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

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.
min
User
Beiträge: 37
Registriert: Dienstag 22. Dezember 2009, 22:25

Ich weiß leider nichts von einem dritten Parameter. Könntest du mich da aufklären? wäre sehr dankbar
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

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.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Der selbe 3. Parameter wie bei

Code: Alles auswählen

con.power
siehe Decimal
the more they change the more they stay the same
Antworten