return Fraction(abs(a._numerator), a._denominator, _normalize=False)
return -(-a._numerator // a._denominator)
return a._numerator // a._denominator
"""Will be math.floor(a) in 3.0."""
return a.numerator // a.denominator
"""Will be math.ceil(a) in 3.0."""
# The negations cleverly convince floordiv to return the ceiling.
return -(-a.numerator // a.denominator)
def __round__(self, ndigits=None):
"""Will be round(self, ndigits) in 3.0.
floor, remainder = divmod(self.numerator, self.denominator)
if remainder * 2 < self.denominator:
elif remainder * 2 > self.denominator:
# Deal with the half case:
# See _operator_fallbacks.forward to check that the results of
# these operations will always be Fraction and therefore have
return Fraction(round(self * shift), shift)
return Fraction(round(self / shift) * shift)
# XXX since this method is expensive, consider caching the result
# In order to make sure that the hash of a Fraction agrees
# with the hash of a numerically equal integer, float or
# Decimal instance, we follow the rules for numeric hashes
# outlined in the documentation. (See library docs, 'Built-in
# dinv is the inverse of self._denominator modulo the prime
# _PyHASH_MODULUS, or 0 if self._denominator is divisible by
dinv = pow(self._denominator, _PyHASH_MODULUS - 2, _PyHASH_MODULUS)
hash_ = abs(self._numerator) * dinv % _PyHASH_MODULUS
result = hash_ if self >= 0 else -hash_
return -2 if result == -1 else result
return a._numerator == b and a._denominator == 1
if isinstance(b, numbers.Rational):
return (a._numerator == b.numerator and
a._denominator == b.denominator)
if isinstance(b, numbers.Complex) and b.imag == 0:
if math.isnan(b) or math.isinf(b):
# comparisons with an infinity or nan should behave in
# the same way for any finite a, so treat a as zero.
return a == a.from_float(b)
# Since a doesn't know how to compare with b, let's give b
# a chance to compare itself with a.
def _richcmp(self, other, op):
"""Helper for comparison operators, for internal use only.
Implement comparison between a Rational instance `self`, and
either another Rational instance or a float `other`. If
`other` is not a Rational instance or a float, return
NotImplemented. `op` should be one of the six standard
# convert other to a Rational instance where reasonable.
if isinstance(other, numbers.Rational):
return op(self._numerator * other.denominator,
self._denominator * other.numerator)
if isinstance(other, float):
if math.isnan(other) or math.isinf(other):
return op(self, self.from_float(other))
return a._richcmp(b, operator.lt)
return a._richcmp(b, operator.gt)
return a._richcmp(b, operator.le)
return a._richcmp(b, operator.ge)
# support for pickling, copy, and deepcopy
return (self.__class__, (str(self),))
if type(self) == Fraction:
return self # I'm immutable; therefore I am my own clone
return self.__class__(self._numerator, self._denominator)
def __deepcopy__(self, memo):
if type(self) == Fraction:
return self # My components are also immutable
return self.__class__(self._numerator, self._denominator)