*** _Rational.py Fri Sep 24 12:26:25 2004 --- Rational.py Fri Sep 24 12:42:46 2004 *************** *** 52,57 **** --- 52,61 ---- 13/10 >>> print rational("1.2e-3") 3/2500 + >>> print rational("-1.3") + -13/10 + >>> print rational("-.25") + -1/4 From ``rational'' literals >>> print rational("1/2") *************** *** 92,98 **** even though naive conversion wouldn't: >>> float(p.n)/float(p.d) ! nan To conserve time, we can trim p: find the closest rational with a bounded denominator --- 96,104 ---- even though naive conversion wouldn't: >>> float(p.n)/float(p.d) ! Traceback (most recent call last): ! File "", line 1, in ? ! OverflowError: long int too large to convert to float To conserve time, we can trim p: find the closest rational with a bounded denominator *************** *** 107,113 **** But we can measure the error as a floating point number to get a rough estimate: >>> float(p.trim(1L<<32)-p) ! -7.3974359428840768e-20 We can also approximate p: find the closest rational which is closer then the bound (shifting rationals is the same as multiplying by 2 to the correct --- 113,119 ---- But we can measure the error as a floating point number to get a rough estimate: >>> float(p.trim(1L<<32)-p) ! -7.3974359428840768e-020 We can also approximate p: find the closest rational which is closer then the bound (shifting rationals is the same as multiplying by 2 to the correct *************** *** 117,132 **** rational(860063L, 114913L) >>> float(p.approximate(rational(1L)>>32)) 7.4844708605640786 ! >>> float(p.approximate(rational(1L)>>32))-p ! 1.3733902903823036e-11 How many bits is that? >>> import math >>> math.log(float(p.approximate(rational(1L)>>32))-p)/math.log(2) ! -36.083467374587123 ! ! Less then -32, or in other words, the rational number we found is about 2.0**-36 further apart, closer then the bound (2.0**-32). ''' --- 123,138 ---- rational(860063L, 114913L) >>> float(p.approximate(rational(1L)>>32)) 7.4844708605640786 ! >>> float(p.approximate(rational(1L)>>32)-p) ! 1.3733999215941832e-011 How many bits is that? >>> import math >>> math.log(float(p.approximate(rational(1L)>>32))-p)/math.log(2) ! -36.083487884637755 ! ! Less than -32, or in other words, the rational number we found is about 2.0**-36 further apart, closer then the bound (2.0**-32). ''' *************** *** 198,204 **** Pass NaNs or infinities at your own risk. >>> rational(10.0) ! rational(10L, 1L) >>> rational(0.0) rational(0L) >>> rational(-.25) --- 204,210 ---- Pass NaNs or infinities at your own risk. >>> rational(10.0) ! rational(10L) >>> rational(0.0) rational(0L) >>> rational(-.25) *************** *** 206,212 **** """ if x == 0: ! return 0L, 1L signbit = 0 if x < 0: x = -x --- 212,218 ---- """ if x == 0: ! return _Rational(0, 1) signbit = 0 if x < 0: x = -x *************** *** 243,249 **** return r ! class _Rational: def __init__(self, n, d): if d == 0: --- 249,255 ---- return r ! class _Rational(object): def __init__(self, n, d): if d == 0: *************** *** 277,312 **** def __rcoerce__(self, other): return coerce(self, other) ! def __add__(self, other): return _Rational(self.n*other.d + other.n*self.d, ! self.d*other.d) def __radd__(self, other): ! return self+other ! ! def __mul__(self, other): return _Rational(self.n*other.n, self.d*other.d) def __rmul__(self, other): ! return self*other def inv(self): return _Rational(self.d, self.n) def __div__(self, other): ! return self*other.inv() def __rdiv__(self, other): ! return self.inv()*other def __neg__(self): return _Rational(-self.n, self.d) def __sub__(self, other): ! return self+(-other) def __rsub__(self, other): ! return (-self)+other def __long__(self): if self.d != 1: --- 283,320 ---- def __rcoerce__(self, other): return coerce(self, other) ! def __add__(self, o): ! other = rational(o) return _Rational(self.n*other.d + other.n*self.d, ! self.d*other.d) def __radd__(self, other): ! return self + rational(other) ! ! def __mul__(self, o): ! other = rational(o) return _Rational(self.n*other.n, self.d*other.d) def __rmul__(self, other): ! return self*rational(other) def inv(self): return _Rational(self.d, self.n) def __div__(self, other): ! return self*rational(other).inv() def __rdiv__(self, other): ! return self.inv()*rational(other) def __neg__(self): return _Rational(-self.n, self.d) def __sub__(self, other): ! return self+(-rational(other)) def __rsub__(self, other): ! return (-self)+rational(other) def __long__(self): if self.d != 1: *************** *** 328,340 **** if isinstance(exp, _Rational): if exp.d == 1: exp = exp.n ! if isinstance(exp, type(1)) or isinstance(exp, type(1L)): if exp < 0: return _Rational(self.d**-exp, self.n**-exp) return _Rational(self.n**exp, self.d**exp) ! return float(self)**exp ! ! def __cmp__(self, other): return cmp(self.n*other.d, self.d*other.n) def __hash__(self): --- 336,352 ---- if isinstance(exp, _Rational): if exp.d == 1: exp = exp.n ! if isinstance(exp, (type(1), type(1L))): if exp < 0: return _Rational(self.d**-exp, self.n**-exp) return _Rational(self.n**exp, self.d**exp) ! return float(self)**float(exp) ! ! def __rpow__(self, base, z=None): ! return rational(base) ** self ! ! def __cmp__(self, o): ! other = rational(o) return cmp(self.n*other.d, self.d*other.n) def __hash__(self): *************** *** 358,372 **** def __hex__(self): return '%s/%s' % (hex(self.n), hex(self.d)) ! def __lshift__(self, other): if other.d != 1: raise TypeError('cannot shift by non-integer') ! return _Rational(self.n<