Ich habe eine große Menge an Python-Code, der Zahlen mit 4 Dezimalstellen zu behandeln versucht und ich bin aus vielen Gründen mit Python 2.4 stecken. Der Code tut sehr vereinfachende Mathematik (es ist ein Kredit-Management-Code, der meist Kredite nimmt oder hinzufügt)Böse in der Python Dezimal/float
Es hat die Verwendung von float und Dezimal vermengt (MySQLdb gibt Dezimalobjekte für SQL DECIMAL-Typen zurück). Nach einigen seltsamen Fehlern, die von der Verwendung herrühren, habe ich die Ursache dafür gefunden, dass einige Stellen im Code floaten und Dezimalzahlen verglichen werden.
Ich habe auf Fälle wie folgt aus:
>>> from decimal import Decimal
>>> max(Decimal('0.06'), 0.6)
Decimal("0.06")
Nun meine Angst ist, dass ich nicht in der Lage sein könnte, alle diese Fälle in den Code zu fangen. (ein normaler Programmierer macht weiterhin x> 0 anstelle von x> Dezimal ('0.0000') und es ist sehr schwer zu vermeiden)
Ich habe einen Patch entwickelt (inspiriert von Verbesserungen des dezimalen Pakets in Python 2.7) .
import decimal
def _convert_other(other):
"""Convert other to Decimal.
Verifies that it's ok to use in an implicit construction.
"""
if isinstance(other, Decimal):
return other
if isinstance(other, (int, long)):
return Decimal(other)
# Our small patch begins
if isinstance(other, float):
return Decimal(str(other))
# Our small patch ends
return NotImplemented
decimal._convert_other = _convert_other
Ich mache es nur in einer sehr frühen Laden Bibliothek, und es wird das Dezimalsystem Paket Verhalten für Schwimmer zu Dezimal Umwandlung vor Vergleichen, indem ändern (zur Vermeidung von Python des Standard-Objekt schlägt Vergleich zum Objekt).
Ich verwendete speziell "str" anstelle von "repr", da es einige Rundungsfälle von Floats behebt. Z.B.
>>> Decimal(str(0.6))
Decimal("0.6")
>>> Decimal(repr(0.6))
Decimal("0.59999999999999998")
Nun meine Frage ist: Fehle ich hier irgendetwas? Ist das ziemlich sicher? oder breche ich hier etwas? (Ich denke, die Autoren des Pakets hatten sehr starke Gründe, schwimmt so viel zu vermeiden)
Nur eine Anmerkung, dass die "Rückgabe NotImplemented" aus dem decimal.py-Paket selbst stammt. Die zwei Zeilen, die ich hinzugefügt habe, sind zwischen den Kommentaren. Ich stimme Ihrer Herangehensweise zu, jedoch erlaubt Python in dieser Implementierung logisch wahnsinnige Vergleiche zwischen Objekten, von denen wir annehmen, dass sie beide Zahlen sind. Hmm, eine andere Idee könnte sein, einen Fehler anstelle einer impliziten Konvertierung zu erzeugen, aber egal, ich denke, ich muss etwas tun ... –
'return NotImplemented' ist korrekt und ist das richtige, [Dokumentation angegeben] (http: // docs .python.org/reference/datamodel.html # emulating-numeric-types), die für einen nicht unterstützten Vergleich zurückgegeben werden soll. Es erlaubt Python, einen anderen Weg zu finden, Dinge zu tun. – aaronasterling
+1 für die Verwendung des Begriffs "Affe Patching", die mich zu Wikipedia führte der Begriff, um zu finden, kommt von "Guerilla Patchen", wie in Guerillakrieg = =). – Tommy