Computing a numeric hash
We do need to define the __hash__()
method properly. See section 4.4.4 of the Python Standard Library for information on computing hash values for numeric types. That section defines a hash_fraction()
function, which is the recommended solution for what we're doing here. Our method looks like the following:
def __hash__( self ):
P = sys.hash_info.modulus
m, n = self.value, self.scale
# Remove common factors of P. (Unnecessary if m and n already coprime.)
while m % P == n % P == 0:
m, n = m // P, n // P
if n % P == 0:
hash_ = sys.hash_info.inf
else:
# Fermat's Little Theorem: pow(n, P-1, P) is 1, so
# pow(n, P-2, P) gives the inverse of n modulo P.
hash_ = (abs(m) % P) * pow(n, P - 2, P) % P
if m < 0:
hash_ = -hash_
if hash_ == -1:
hash_ = -2
return hash_
This reduces a two-part rational fraction value to...