[Python-Dev] Decimal <-> float comparisons in py3k.

Mark Dickinson dickinsm at gmail.com
Wed Mar 17 15:41:49 CET 2010


On Wed, Mar 17, 2010 at 11:43 AM, Steven D'Aprano <steve at pearwood.info> wrote:
> Having said all that, I've just re-read the PEP, and spotted a fly in
> the ointment... hash.
>
> If we allow Decimals to compare equal to floats, that presumably implies
> that they need to hash equal. That may be simple enough for integer
> valued floats, but what non-integer values?

That is indeed an issue.  It can be taken care by checking whether the
Decimal instance is exactly representable as a float, and returning
the hash of the corresponding float if so.  From the patch
(http://bugs.python.org/file16544/issue2531.patch):

+        self_as_float = float(self)
+        if Decimal.from_float(self_as_float) == self:
+            return hash(self_as_float)

Strictly speaking this only works if the Decimal -> float conversion
(which relies on the platform strtod) is accurate to within <1ulp, but
that's going to be true in 2.7/3.x on all platforms using David Gay's
str<->float conversion code, and is *probably* true for the system
strtod on any sane platform, so I don't think it's a real issue.

This also slows down the (already slow) hash computation for Decimal a
touch.  Until people start complaining, or show evidence of
applications that require making large dictionaries of Decimal
instances, I'm not going to worry about that either.  It would be easy
to cache the hash value of a Decimal instance if it became necessary.

A less messy (but more intrusive) alternative would be to come up with
a single sane hash function defined for all rational numbers (plus
infinities and nans), and use this function for int, long, float,
Decimal and Fraction types.  I have a candidate function in mind...

Mark


More information about the Python-Dev mailing list