[Python-checkins] python/nondist/sandbox/rational Rational.py, 1.2,
1.3
loewis at users.sourceforge.net
loewis at users.sourceforge.net
Sat Sep 18 17:30:59 CEST 2004
Update of /cvsroot/python/python/nondist/sandbox/rational
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv14545
Modified Files:
Rational.py
Log Message:
untabify.
Index: Rational.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/rational/Rational.py,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- Rational.py 25 Nov 2003 21:20:42 -0000 1.2
+++ Rational.py 18 Sep 2004 15:30:57 -0000 1.3
@@ -131,311 +131,311 @@
'''
def _gcd(a, b):
- if a>b:
- b, a = a, b
- if a == 0:
- return b
- while 1:
- c = b % a
- if c == 0:
- return a
- b = a
- a = c
+ if a>b:
+ b, a = a, b
+ if a == 0:
+ return b
+ while 1:
+ c = b % a
+ if c == 0:
+ return a
+ b = a
+ a = c
def _trim(n, d, max_d):
- if max_d == 1:
- return n/d, 1
- last_n, last_d = 0, 1
- current_n, current_d = 1, 0
- while 1:
- div, mod = divmod(n, d)
- n, d = d, mod
- before_last_n, before_last_d = last_n, last_d
- next_n = last_n + current_n*div
- next_d = last_d + current_d*div
- last_n, last_d = current_n, current_d
- current_n, current_d = next_n, next_d
- if mod == 0 or current_d>=max_d:
- break
- if current_d == max_d:
- return current_n, current_d
- i = (max_d-before_last_d)/last_d
- alternative_n = before_last_n + i*last_n
- alternative_d = before_last_d + i*last_d
+ if max_d == 1:
+ return n/d, 1
+ last_n, last_d = 0, 1
+ current_n, current_d = 1, 0
+ while 1:
+ div, mod = divmod(n, d)
+ n, d = d, mod
+ before_last_n, before_last_d = last_n, last_d
+ next_n = last_n + current_n*div
+ next_d = last_d + current_d*div
+ last_n, last_d = current_n, current_d
+ current_n, current_d = next_n, next_d
+ if mod == 0 or current_d>=max_d:
+ break
+ if current_d == max_d:
+ return current_n, current_d
+ i = (max_d-before_last_d)/last_d
+ alternative_n = before_last_n + i*last_n
+ alternative_d = before_last_d + i*last_d
alternative = _Rational(alternative_n, alternative_d)
last = _Rational(last_n, last_d)
- num = _Rational(n, d)
- if abs(alternative-num)<abs(last-num):
- return alternative_n, alternative_d
- else:
- return last_n, last_d
+ num = _Rational(n, d)
+ if abs(alternative-num)<abs(last-num):
+ return alternative_n, alternative_d
+ else:
+ return last_n, last_d
def _approximate(n, d, err):
- r = _Rational(n, d)
- last_n, last_d = 0, 1
- current_n, current_d = 1, 0
- while 1:
- div, mod = divmod(n, d)
- n, d = d, mod
- next_n = last_n + current_n*div
- next_d = last_d + current_d*div
- last_n, last_d = current_n, current_d
- current_n, current_d = next_n, next_d
- app = _Rational(current_n, current_d)
- if mod == 0 or abs(app-r)<err:
- break
- return app
+ r = _Rational(n, d)
+ last_n, last_d = 0, 1
+ current_n, current_d = 1, 0
+ while 1:
+ div, mod = divmod(n, d)
+ n, d = d, mod
+ next_n = last_n + current_n*div
+ next_d = last_d + current_d*div
+ last_n, last_d = current_n, current_d
+ current_n, current_d = next_n, next_d
+ app = _Rational(current_n, current_d)
+ if mod == 0 or abs(app-r)<err:
+ break
+ return app
import math as _math
def _float_to_ratio(x):
- """\
- x -> (top, bot), a pair of co-prime longs s.t. x = top/bot.
+ """\
+ x -> (top, bot), a pair of co-prime longs s.t. x = top/bot.
- The conversion is done exactly, without rounding.
- bot > 0 guaranteed.
- Some form of binary fp is assumed.
- Pass NaNs or infinities at your own risk.
+ The conversion is done exactly, without rounding.
+ bot > 0 guaranteed.
+ Some form of binary fp is assumed.
+ Pass NaNs or infinities at your own risk.
- >>> rational(10.0)
- rational(10L, 1L)
- >>> rational(0.0)
- rational(0L)
- >>> rational(-.25)
- rational(-1L, 4L)
- """
+ >>> rational(10.0)
+ rational(10L, 1L)
+ >>> rational(0.0)
+ rational(0L)
+ >>> rational(-.25)
+ rational(-1L, 4L)
+ """
- if x == 0:
- return 0L, 1L
- signbit = 0
- if x < 0:
- x = -x
- signbit = 1
- f, e = _math.frexp(x)
- assert 0.5 <= f < 1.0
- # x = f * 2**e exactly
+ if x == 0:
+ return 0L, 1L
+ signbit = 0
+ if x < 0:
+ x = -x
+ signbit = 1
+ f, e = _math.frexp(x)
+ assert 0.5 <= f < 1.0
+ # x = f * 2**e exactly
- # Suck up CHUNK bits at a time; 28 is enough so that we suck
- # up all bits in 2 iterations for all known binary double-
- # precision formats, and small enough to fit in an int.
- CHUNK = 28
- top = 0L
- # invariant: x = (top + f) * 2**e exactly
- while f:
- f = _math.ldexp(f, CHUNK)
- digit = int(f)
- assert digit >> CHUNK == 0
- top = (top << CHUNK) | digit
- f = f - digit
- assert 0.0 <= f < 1.0
- e = e - CHUNK
- assert top
+ # Suck up CHUNK bits at a time; 28 is enough so that we suck
+ # up all bits in 2 iterations for all known binary double-
+ # precision formats, and small enough to fit in an int.
+ CHUNK = 28
+ top = 0L
+ # invariant: x = (top + f) * 2**e exactly
+ while f:
+ f = _math.ldexp(f, CHUNK)
+ digit = int(f)
+ assert digit >> CHUNK == 0
+ top = (top << CHUNK) | digit
+ f = f - digit
+ assert 0.0 <= f < 1.0
+ e = e - CHUNK
+ assert top
- # now x = top * 2**e exactly; fold in 2**e
- r = _Rational(top, 1)
- if e>0:
- r = r << e
- else:
- r = r >> -e
- if signbit:
- return -r
- else:
- return r
+ # now x = top * 2**e exactly; fold in 2**e
+ r = _Rational(top, 1)
+ if e>0:
+ r = r << e
+ else:
+ r = r >> -e
+ if signbit:
+ return -r
+ else:
+ return r
class _Rational:
- def __init__(self, n, d):
- if d == 0:
- return n/d
- n, d = map(long, (n, d))
- if d < 0:
- n *= -1
- d *= -1
- f = _gcd(abs(n), d)
- self.n = n/f
- self.d = d/f
+ def __init__(self, n, d):
+ if d == 0:
+ return n/d
+ n, d = map(long, (n, d))
+ if d < 0:
+ n *= -1
+ d *= -1
+ f = _gcd(abs(n), d)
+ self.n = n/f
+ self.d = d/f
- def __repr__(self):
- if self.d == 1:
- return 'rational(%r)' % self.n
- return 'rational(%(n)r, %(d)r)' % self.__dict__
+ def __repr__(self):
+ if self.d == 1:
+ return 'rational(%r)' % self.n
+ return 'rational(%(n)r, %(d)r)' % self.__dict__
- def __str__(self):
- if self.d == 1:
- return str(self.n)
- return '%(n)s/%(d)s' % self.__dict__
+ def __str__(self):
+ if self.d == 1:
+ return str(self.n)
+ return '%(n)s/%(d)s' % self.__dict__
- def __coerce__(self, other):
- for int in (type(1), type(1L)):
- if isinstance(other, int):
- return self, rational(other)
- if type(other) == type(1.0):
- return float(self), other
- return NotImplemented
+ def __coerce__(self, other):
+ for int in (type(1), type(1L)):
+ if isinstance(other, int):
+ return self, rational(other)
+ if type(other) == type(1.0):
+ return float(self), other
+ return NotImplemented
- def __rcoerce__(self, other):
- return coerce(self, other)
+ 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 __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 __radd__(self, other):
+ return self+other
- def __mul__(self, other):
- return _Rational(self.n*other.n, self.d*other.d)
+ def __mul__(self, other):
+ return _Rational(self.n*other.n, self.d*other.d)
- def __rmul__(self, other):
- return self*other
+ def __rmul__(self, other):
+ return self*other
- def inv(self):
- return _Rational(self.d, self.n)
+ def inv(self):
+ return _Rational(self.d, self.n)
- def __div__(self, other):
- return self*other.inv()
+ def __div__(self, other):
+ return self*other.inv()
- def __rdiv__(self, other):
- return self.inv()*other
+ def __rdiv__(self, other):
+ return self.inv()*other
- def __neg__(self):
- return _Rational(-self.n, self.d)
+ def __neg__(self):
+ return _Rational(-self.n, self.d)
- def __sub__(self, other):
- return self+(-other)
+ def __sub__(self, other):
+ return self+(-other)
- def __rsub__(self, other):
- return (-self)+other
+ def __rsub__(self, other):
+ return (-self)+other
- def __long__(self):
- if self.d != 1:
- raise ValueError('cannot convert non-integer')
- return self.n
+ def __long__(self):
+ if self.d != 1:
+ raise ValueError('cannot convert non-integer')
+ return self.n
- def __int__(self):
- return int(long(self))
+ def __int__(self):
+ return int(long(self))
- def __float__(self):
- # Avoid NaNs like the plague
- if self.d > 1L<<1023:
- self = self.trim(1L<<1023)
- return float(self.n)/float(self.d)
+ def __float__(self):
+ # Avoid NaNs like the plague
+ if self.d > 1L<<1023:
+ self = self.trim(1L<<1023)
+ return float(self.n)/float(self.d)
- def __pow__(self, exp, z=None):
- if z is not None:
- raise TypeError('pow with 3 args unsupported')
- 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 __pow__(self, exp, z=None):
+ if z is not None:
+ raise TypeError('pow with 3 args unsupported')
+ 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 __cmp__(self, other):
+ return cmp(self.n*other.d, self.d*other.n)
- def __hash__(self):
- return hash(self.n)^hash(self.d)
+ def __hash__(self):
+ return hash(self.n)^hash(self.d)
- def __abs__(self):
- return _Rational(abs(self.n), self.d)
+ def __abs__(self):
+ return _Rational(abs(self.n), self.d)
- def __complex__(self):
- return complex(float(self))
+ def __complex__(self):
+ return complex(float(self))
- def __nonzero__(self):
- return self.n != 0
+ def __nonzero__(self):
+ return self.n != 0
- def __pos__(self):
- return self
+ def __pos__(self):
+ return self
- def __oct__(self):
- return '%s/%s' % (oct(self.n), oct(self.d))
+ def __oct__(self):
+ return '%s/%s' % (oct(self.n), oct(self.d))
- def __hex__(self):
- return '%s/%s' % (hex(self.n), hex(self.d))
+ 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<<other.n, self.d)
+ def __lshift__(self, other):
+ if other.d != 1:
+ raise TypeError('cannot shift by non-integer')
+ return _Rational(self.n<<other.n, self.d)
- def __rshift__(self, other):
- if other.d != 1:
- raise TypeError('cannot shift by non-integer')
- return _Rational(self.n, self.d<<other.n)
+ def __rshift__(self, other):
+ if other.d != 1:
+ raise TypeError('cannot shift by non-integer')
+ return _Rational(self.n, self.d<<other.n)
- def trim(self, max_d):
- n, d = self.n, self.d
- if n < 0:
- n *= -1
- n, d = _trim(n, d, max_d)
- if self.n < 0:
- n *= -1
- r = _Rational(n, d)
- upwards = self < r
- if upwards:
- alternate_n = n-1
- else:
- alternate_n = n+1
- if self == _Rational(alternate_n+n, d*2):
- new_n = min(alternate_n, n)
- return _Rational(new_n, d)
- return r
+ def trim(self, max_d):
+ n, d = self.n, self.d
+ if n < 0:
+ n *= -1
+ n, d = _trim(n, d, max_d)
+ if self.n < 0:
+ n *= -1
+ r = _Rational(n, d)
+ upwards = self < r
+ if upwards:
+ alternate_n = n-1
+ else:
+ alternate_n = n+1
+ if self == _Rational(alternate_n+n, d*2):
+ new_n = min(alternate_n, n)
+ return _Rational(new_n, d)
+ return r
- def approximate(self, err):
- n, d = self.n, self.d
- if n < 0:
- n *= -1
- app = _approximate(n, d, err)
- if self.n < 0:
- app *= -1
- return app
+ def approximate(self, err):
+ n, d = self.n, self.d
+ if n < 0:
+ n *= -1
+ app = _approximate(n, d, err)
+ if self.n < 0:
+ app *= -1
+ return app
def _parse_number(num):
- if '/' in num:
- n, d = num.split('/', 1)
- return _parse_number(n)/_parse_number(d)
- if 'e' in num:
- mant, exp = num.split('e', 1)
- mant = _parse_number(mant)
- exp = long(exp)
- return mant*(rational(10)**rational(exp))
- if '.' in num:
- i, f = num.split('.', 1)
- i = long(i)
- f = rational(long(f), 10L**len(f))
- return i+f
- return rational(long(num))
+ if '/' in num:
+ n, d = num.split('/', 1)
+ return _parse_number(n)/_parse_number(d)
+ if 'e' in num:
+ mant, exp = num.split('e', 1)
+ mant = _parse_number(mant)
+ exp = long(exp)
+ return mant*(rational(10)**rational(exp))
+ if '.' in num:
+ i, f = num.split('.', 1)
+ i = long(i)
+ f = rational(long(f), 10L**len(f))
+ return i+f
+ return rational(long(num))
def rational(n, d=1L):
- if type(n) in (type(''), type(u'')) :
- n = _parse_number(n)
- if type(d) in (type(''), type(u'')) :
- d = _parse_number(d)
- if isinstance(n, type(1.0)):
- n = _float_to_ratio(n)
- if isinstance(d, type(1.0)):
- d = _float_to_ratio(d)
- for arg in (n, d):
- if isinstance(arg, type(1j)):
- raise TypeError('cannot convert arguments')
- if isinstance(n, _Rational):
- return rational(n.n, n.d*d)
- if isinstance(d, _Rational):
- return rational(n*d.d, d.n)
- return _Rational(n, d)
+ if type(n) in (type(''), type(u'')) :
+ n = _parse_number(n)
+ if type(d) in (type(''), type(u'')) :
+ d = _parse_number(d)
+ if isinstance(n, type(1.0)):
+ n = _float_to_ratio(n)
+ if isinstance(d, type(1.0)):
+ d = _float_to_ratio(d)
+ for arg in (n, d):
+ if isinstance(arg, type(1j)):
+ raise TypeError('cannot convert arguments')
+ if isinstance(n, _Rational):
+ return rational(n.n, n.d*d)
+ if isinstance(d, _Rational):
+ return rational(n*d.d, d.n)
+ return _Rational(n, d)
import __builtin__
__builtin__.rational = rational
def _test():
- import doctest, Rational
- doctest.testmod(Rational)
+ import doctest, Rational
+ doctest.testmod(Rational)
if __name__ == '__main__':
- _test()
+ _test()
More information about the Python-checkins
mailing list