diff options
author | Facundo Batista <facundobatista@gmail.com> | 2008-01-08 12:25:20 (GMT) |
---|---|---|
committer | Facundo Batista <facundobatista@gmail.com> | 2008-01-08 12:25:20 (GMT) |
commit | 52b25795c02442fc40f8932d05e5d728266339a4 (patch) | |
tree | 6bd1515a655c8d46c892a9044f2aa10cf78152c8 | |
parent | f66f95d419776bdb4fe0d3c9b8d848d3321a645b (diff) | |
download | cpython-52b25795c02442fc40f8932d05e5d728266339a4.zip cpython-52b25795c02442fc40f8932d05e5d728266339a4.tar.gz cpython-52b25795c02442fc40f8932d05e5d728266339a4.tar.bz2 |
Issue #1757: The hash of a Decimal instance is no longer affected
by the current context. Thanks Mark Dickinson.
-rw-r--r-- | Lib/decimal.py | 14 | ||||
-rw-r--r-- | Lib/test/test_decimal.py | 17 | ||||
-rw-r--r-- | Misc/NEWS | 3 |
3 files changed, 31 insertions, 3 deletions
diff --git a/Lib/decimal.py b/Lib/decimal.py index 257ba0c..3ee078f 100644 --- a/Lib/decimal.py +++ b/Lib/decimal.py @@ -788,8 +788,10 @@ class Decimal(object): def __hash__(self): """x.__hash__() <==> hash(x)""" # Decimal integers must hash the same as the ints - # Non-integer decimals are normalized and hashed as strings - # Normalization assures that hash(100E-1) == hash(10) + # + # The hash of a nonspecial noninteger Decimal must depend only + # on the value of that Decimal, and not on its representation. + # For example: hash(Decimal("100E-1")) == hash(Decimal("10")). if self._is_special: if self._isnan(): raise TypeError('Cannot hash a NaN value.') @@ -805,7 +807,13 @@ class Decimal(object): # 2**64-1. So we can replace hash((-1)**s*c*10**e) with # hash((-1)**s*c*pow(10, e, 2**64-1). return hash((-1)**op.sign*op.int*pow(10, op.exp, 2**64-1)) - return hash(str(self.normalize())) + # The value of a nonzero nonspecial Decimal instance is + # faithfully represented by the triple consisting of its sign, + # its adjusted exponent, and its coefficient with trailing + # zeros removed. + return hash((self._sign, + self._exp+len(self._int), + self._int.rstrip('0'))) def as_tuple(self): """Represents the number as a triple tuple. diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py index dbe7023..03cff60 100644 --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -980,6 +980,23 @@ class DecimalUsabilityTest(unittest.TestCase): self.assert_(hash(Decimal('Inf'))) self.assert_(hash(Decimal('-Inf'))) + # check that the value of the hash doesn't depend on the + # current context (issue #1757) + c = getcontext() + old_precision = c.prec + x = Decimal("123456789.1") + + c.prec = 6 + h1 = hash(x) + c.prec = 10 + h2 = hash(x) + c.prec = 16 + h3 = hash(x) + + self.assertEqual(h1, h2) + self.assertEqual(h1, h3) + c.prec = old_precision + def test_min_and_max_methods(self): d1 = Decimal('15.32') @@ -348,6 +348,9 @@ Core and builtins Library ------- +- Issue #1757: The hash of a Decimal instance is no longer affected by + the current context. + - Patch #467924: add ZipFile.extract() and ZipFile.extractall() in the zipfile module. |