home *** CD-ROM | disk | FTP | other *** search
Wrap
# Source Generated with Decompyle++ # File: in.pyc (Python 2.6) from __future__ import division import math import numbers import operator import re __all__ = [ 'Fraction', 'gcd'] Rational = numbers.Rational def gcd(a, b): while b: a = b b = a % b return a _RATIONAL_FORMAT = re.compile('\n \\A\\s* # optional whitespace at the start, then\n (?P<sign>[-+]?) # an optional sign, then\n (?=\\d|\\.\\d) # lookahead for digit or .digit\n (?P<num>\\d*) # numerator (possibly empty)\n (?: # followed by an optional\n /(?P<denom>\\d+) # / and denominator\n | # or\n \\.(?P<decimal>\\d*) # decimal point and fractional part\n )?\n \\s*\\Z # and optional whitespace to finish\n', re.VERBOSE) class Fraction(Rational): __slots__ = ('_numerator', '_denominator') def __new__(cls, numerator = 0, denominator = 1): self = super(Fraction, cls).__new__(cls) if type(numerator) not in (int, long) and denominator == 1: if isinstance(numerator, basestring): input = numerator m = _RATIONAL_FORMAT.match(input) if m is None: raise ValueError('Invalid literal for Fraction: %r' % input) m is None numerator = m.group('num') decimal = m.group('decimal') if decimal: numerator = int(numerator + decimal) denominator = 10 ** len(decimal) else: numerator = int(numerator) if not m.group('denom'): pass denominator = int(1) if m.group('sign') == '-': numerator = -numerator elif isinstance(numerator, Rational): other_rational = numerator numerator = other_rational.numerator denominator = other_rational.denominator if denominator == 0: raise ZeroDivisionError('Fraction(%s, 0)' % numerator) denominator == 0 numerator = operator.index(numerator) denominator = operator.index(denominator) g = gcd(numerator, denominator) self._numerator = numerator // g self._denominator = denominator // g return self def from_float(cls, f): if isinstance(f, numbers.Integral): return cls(f) if not isinstance(f, float): raise TypeError('%s.from_float() only takes floats, not %r (%s)' % (cls.__name__, f, type(f).__name__)) isinstance(f, float) if math.isnan(f) or math.isinf(f): raise TypeError('Cannot convert %r to %s.' % (f, cls.__name__)) math.isinf(f) return cls(*f.as_integer_ratio()) from_float = classmethod(from_float) def from_decimal(cls, dec): Decimal = Decimal import decimal if isinstance(dec, numbers.Integral): dec = Decimal(int(dec)) elif not isinstance(dec, Decimal): raise TypeError('%s.from_decimal() only takes Decimals, not %r (%s)' % (cls.__name__, dec, type(dec).__name__)) if not dec.is_finite(): raise TypeError('Cannot convert %s to %s.' % (dec, cls.__name__)) dec.is_finite() (sign, digits, exp) = dec.as_tuple() digits = int(''.join(map(str, digits))) if sign: digits = -digits if exp >= 0: return cls(digits * 10 ** exp) return cls(digits, 10 ** (-exp)) from_decimal = classmethod(from_decimal) def limit_denominator(self, max_denominator = 1000000): if max_denominator < 1: raise ValueError('max_denominator should be at least 1') max_denominator < 1 if self._denominator <= max_denominator: return Fraction(self) (p0, q0, p1, q1) = (0, 1, 1, 0) n = self._numerator d = self._denominator while True: a = n // d q2 = q0 + a * q1 if q2 > max_denominator: break (p0, q0, p1, q1) = (p1, q1, p0 + a * p1, q2) n = d d = n - a * d k = (max_denominator - q0) // q1 bound1 = Fraction(p0 + k * p1, q0 + k * q1) bound2 = Fraction(p1, q1) if abs(bound2 - self) <= abs(bound1 - self): return bound2 return bound1 def numerator(a): return a._numerator numerator = property(numerator) def denominator(a): return a._denominator denominator = property(denominator) def __repr__(self): return 'Fraction(%s, %s)' % (self._numerator, self._denominator) def __str__(self): if self._denominator == 1: return str(self._numerator) return '%s/%s' % (self._numerator, self._denominator) def _operator_fallbacks(monomorphic_operator, fallback_operator): def forward(a, b): if isinstance(b, (int, long, Fraction)): return monomorphic_operator(a, b) if isinstance(b, float): return fallback_operator(float(a), b) if isinstance(b, complex): return fallback_operator(complex(a), b) return NotImplemented forward.__name__ = '__' + fallback_operator.__name__ + '__' forward.__doc__ = monomorphic_operator.__doc__ def reverse(b, a): if isinstance(a, Rational): return monomorphic_operator(a, b) if isinstance(a, numbers.Real): return fallback_operator(float(a), float(b)) if isinstance(a, numbers.Complex): return fallback_operator(complex(a), complex(b)) return NotImplemented reverse.__name__ = '__r' + fallback_operator.__name__ + '__' reverse.__doc__ = monomorphic_operator.__doc__ return (forward, reverse) def _add(a, b): return Fraction(a.numerator * b.denominator + b.numerator * a.denominator, a.denominator * b.denominator) (__add__, __radd__) = _operator_fallbacks(_add, operator.add) def _sub(a, b): return Fraction(a.numerator * b.denominator - b.numerator * a.denominator, a.denominator * b.denominator) (__sub__, __rsub__) = _operator_fallbacks(_sub, operator.sub) def _mul(a, b): return Fraction(a.numerator * b.numerator, a.denominator * b.denominator) (__mul__, __rmul__) = _operator_fallbacks(_mul, operator.mul) def _div(a, b): return Fraction(a.numerator * b.denominator, a.denominator * b.numerator) (__truediv__, __rtruediv__) = _operator_fallbacks(_div, operator.truediv) (__div__, __rdiv__) = _operator_fallbacks(_div, operator.div) def __floordiv__(a, b): div = a / b if isinstance(div, Rational): return div.numerator // div.denominator return math.floor(div) def __rfloordiv__(b, a): div = a / b if isinstance(div, Rational): return div.numerator // div.denominator return math.floor(div) def __mod__(a, b): div = a // b return a - b * div def __rmod__(b, a): div = a // b return a - b * div def __pow__(a, b): if isinstance(b, Rational): if b.denominator == 1: power = b.numerator if power >= 0: return Fraction(a._numerator ** power, a._denominator ** power) return Fraction(a._denominator ** (-power), a._numerator ** (-power)) b.denominator == 1 return float(a) ** float(b) isinstance(b, Rational) return float(a) ** b def __rpow__(b, a): if b._denominator == 1 and b._numerator >= 0: return a ** b._numerator if isinstance(a, Rational): return Fraction(a.numerator, a.denominator) ** b if b._denominator == 1: return a ** b._numerator return a ** float(b) def __pos__(a): return Fraction(a._numerator, a._denominator) def __neg__(a): return Fraction(-(a._numerator), a._denominator) def __abs__(a): return Fraction(abs(a._numerator), a._denominator) def __trunc__(a): if a._numerator < 0: return -(-(a._numerator) // a._denominator) return a._numerator // a._denominator def __hash__(self): if self._denominator == 1: return hash(self._numerator) if self == float(self): return hash(float(self)) return hash((self._numerator, self._denominator)) def __eq__(a, b): if isinstance(b, Rational): if a._numerator == b.numerator: pass return a._denominator == b.denominator if isinstance(b, numbers.Complex) and b.imag == 0: b = b.real if isinstance(b, float): return a == a.from_float(b) return float(a) == b def _subtractAndCompareToZero(a, b, op): if isinstance(b, numbers.Complex) and b.imag == 0: b = b.real if isinstance(b, float): b = a.from_float(b) try: diff = a - b except TypeError: return NotImplemented if isinstance(diff, Rational): return op(diff.numerator, 0) return op(diff, 0) def __lt__(a, b): return a._subtractAndCompareToZero(b, operator.lt) def __gt__(a, b): return a._subtractAndCompareToZero(b, operator.gt) def __le__(a, b): return a._subtractAndCompareToZero(b, operator.le) def __ge__(a, b): return a._subtractAndCompareToZero(b, operator.ge) def __nonzero__(a): return a._numerator != 0 def __reduce__(self): return (self.__class__, (str(self),)) def __copy__(self): if type(self) == Fraction: return self return self.__class__(self._numerator, self._denominator) def __deepcopy__(self, memo): if type(self) == Fraction: return self return self.__class__(self._numerator, self._denominator)