Decimal Implementierung
Verfasst: Montag 12. Juli 2010, 08:52
Hallo,
ich habe mir eine Klasse geschrieben, die mir das Rechnen mit Gewichten ermöglicht à la 0.2g + 2.1 kg = 2.3kg. Für die Klasse habe ich auch die Rich Comparison Methoden implementiert. Jetzt ist mir bei Vergleichtests aufgefallen, dass Gewichte, die gleich sein sollten, nicht gleich sind. Schuld ist wohl die Floating Point Problematik. Ich konnte das Problem folgendermaßen isolieren:
Nun kann ich ja mittels Decimal beim Vergleichen ein "richtiges" Ergebnis erhalten:
Wie kann ich jetzt "Decimal" am besten in meinen bestehenden Code implementieren, um Gewichte vergleichen zu können? Einfach jede Berechnung in Decimal konvertieren? Oder kann man da geschickt etwas mit Vererbung machen, indem man von Decimal erbt? Ungeschickter Weise habe ich den Code leider zu Hause auf meinem Rechner gelassen und kann erst heute abend die Klasse posten. Deshalb aus dem Kopf:
Würde es bereits aureichen, self.value als Decimal zu schreiben? Denn man kann ja so weiterrechnen ...
Danke,
Frank
ich habe mir eine Klasse geschrieben, die mir das Rechnen mit Gewichten ermöglicht à la 0.2g + 2.1 kg = 2.3kg. Für die Klasse habe ich auch die Rich Comparison Methoden implementiert. Jetzt ist mir bei Vergleichtests aufgefallen, dass Gewichte, die gleich sein sollten, nicht gleich sind. Schuld ist wohl die Floating Point Problematik. Ich konnte das Problem folgendermaßen isolieren:
Code: Alles auswählen
>>> foo = 0.0238
>>> bar = 0.022 + 0.0018
>>> foo == bar
False
Code: Alles auswählen
>>> foo = Decimal(str(0.0238))
>>> bar = Decimal(str(0.022)) + Decimal(str(0.0018))
>>> foo == bar
True
Code: Alles auswählen
class Weight(object):
def __init__(self, value, unit="g"):
self.value = value
self.unit = unit
self.si_prefix = unit[0:1]
self.si_prefixes = { 'µ' : 6, 'm': 3, 'k': -3}
@property
def base_value(self):
# so ungefähr ;-)
# genaueres später
if self.unit == "g":
return self.value
else:
return self.value * 10**(self.si_prefixes[self.si_prefix]*-1)
Code: Alles auswählen
>>> bar * 2
Decimal('0.0476')
Frank