cofi hat geschrieben:Lesen & verstehen:
http://floating-point-gui.de/
Danach weisst du auch, dass der Weg aus Floats Strings und danach Decimal zu machen im Allgemeinen falsch sein muss.
`decimal` ist auch nicht beliebig genau, wie du aus der Doku entnehmen kannst, und um ein vielfaches langsamer.
Du solltest aber erst einmal verstehen warum sich Floats so verhalten wie sie es tun.
"warum sie sich so verhalten" - reicht es da nicht einfach so wissen, "ist halt so bei computern" ?
Im Link wird heriauf verwiesen, wenn man exakt rechnen will:
http://floating-point-gui.de/formats/exact/
aber da steht nicht, wie man die 3 vorgestellten Arten nun verwenden kann...
BlackJack hat geschrieben:@Serpens66: Hat man denn so viele Float-Literale im Code? Notfalls kann man die mit regulären Ausdrücken suchen und ersetzen — das kann eigentlich jeder vernünftige Editor, oder man nimmt das `ast`-Modul um `float`-Literale zu finden.
Wobei ich ja erst einmal ausrechnen würde ob `float` tatsächlich zu ungenau ist, für den Einsatzzweck, denn `Decimal` ist deutlich langsamer.
Naja, so einfach ist das jetzt nicht, alles float in decimal umzuwandeln. Denn ich hab ja nicht überall "float()" stehen, was ich nun infach in decimal umwandeln kann. So habe ich z.b einfach 1.1 da stehen, was ja automatisch float ist. Es wäre also schon einiges an Arbeit, wenn ich alles umwandeln wuerde. Aber vorher werde ich denke ich auch nochmal genauer nachschauen, wie viel mehr Zeit dadurch auf dem Pi gebraucht wird.
bisher habe ich das Problem immer mit round umgangen. In den meisten Fällen ist das auch ausreichend, weshalb ich vermutlich nicht das ganze skript umschreiben muss.
Allerdings habe ich z.b folgende fkt, bei welcher die "bishermenge" zum schluss exakt so gro sein soll, wie die maxmenge (auf 2 kommastellen genau).
Code: Alles auswählen
maxmenge = 1.5
list = [{"menge":0.12,"preis":200.11,"restmenge":0.12},{"menge":0.34,"preis":200.13,"restmenge":0.34},{"menge":0.02,"preis":201.05,"restmenge":0.02},...] # halt noch viele weitere einträge
for entry in list:
if bishermenge == maxmenge:
break
rest = maxmenge - bishermenge
if rest >= entry["restmenge"]:
verwendete_Menge = self.abrunder(entry["restmenge"],2)
entry["restmenge"] = 0 #hier egal, wenn eigentlich noch kleine bruchstücke über sind
elif rest< entry["restmenge"]:
verwendete_Menge = self.abrunder(rest,2)
entry["restmenge"] = entry["restmenge"] - rest
bishermenge += verwendete_Menge
Das Problem hierbei ist nun, dass "rest = maxmenge - bishermenge", potentiell sowas wie 0.27999999 ergeben kann, wenn eigentlich 0.28 rauskommen sollte. Weil ich das nun abrunde (aufrunden darf ich nicht, da ich nicht mehr nehmen darf, als vorhanden), lande ich bei 0.27, was bei den aktuellen größenordnungen schon eine sehr große abweichung und nicht okay ist.
Daher sehe ich an dieser Stelle keinen anderen Weg, als Decimal zu verwenden.