mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
Merged revisions 59952-59984 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r59952 | thomas.heller | 2008-01-14 02:35:28 -0800 (Mon, 14 Jan 2008) | 1 line Issue 1821: configure libffi for amd64 on FreeeBSD. ........ r59953 | andrew.kuchling | 2008-01-14 06:48:43 -0800 (Mon, 14 Jan 2008) | 1 line Update description of float_info ........ r59959 | raymond.hettinger | 2008-01-14 14:58:05 -0800 (Mon, 14 Jan 2008) | 1 line Fix 1698398: Zipfile.printdir() crashed because the format string expected a tuple object of length six instead of a time.struct_time object. ........ r59961 | andrew.kuchling | 2008-01-14 17:29:16 -0800 (Mon, 14 Jan 2008) | 1 line Typo fixes ........ r59962 | andrew.kuchling | 2008-01-14 17:29:44 -0800 (Mon, 14 Jan 2008) | 1 line Markup fix ........ r59963 | andrew.kuchling | 2008-01-14 17:47:32 -0800 (Mon, 14 Jan 2008) | 1 line Add many items ........ r59964 | andrew.kuchling | 2008-01-14 17:55:32 -0800 (Mon, 14 Jan 2008) | 1 line Repair unfinished sentence ........ r59967 | raymond.hettinger | 2008-01-14 19:02:37 -0800 (Mon, 14 Jan 2008) | 5 lines Issue 1820: structseq objects did not work with the % formatting operator or isinstance(t, tuple). Orignal patch (without tests) by Leif Walsh. ........ r59968 | raymond.hettinger | 2008-01-14 19:07:42 -0800 (Mon, 14 Jan 2008) | 1 line Tighten the definition of a named tuple. ........ r59969 | skip.montanaro | 2008-01-14 19:40:20 -0800 (Mon, 14 Jan 2008) | 3 lines Better (?) text describing the lack of guarantees provided by qsize(), empty() and full(). ........ r59970 | raymond.hettinger | 2008-01-14 21:39:59 -0800 (Mon, 14 Jan 2008) | 1 line Temporarily revert 59967 until GC can be added. ........ r59971 | raymond.hettinger | 2008-01-14 21:46:43 -0800 (Mon, 14 Jan 2008) | 1 line Small grammar nit ........ r59972 | georg.brandl | 2008-01-14 22:55:56 -0800 (Mon, 14 Jan 2008) | 2 lines Typo. ........ r59973 | georg.brandl | 2008-01-14 22:58:15 -0800 (Mon, 14 Jan 2008) | 2 lines Remove duplicate entry. ........ r59974 | jeffrey.yasskin | 2008-01-14 23:46:24 -0800 (Mon, 14 Jan 2008) | 12 lines Add rational.Rational as an implementation of numbers.Rational with infinite precision. This has been discussed at http://bugs.python.org/issue1682. It's useful primarily for teaching, but it also demonstrates how to implement a member of the numeric tower, including fallbacks for mixed-mode arithmetic. I expect to write a couple more patches in this area: * Rational.from_decimal() * Rational.trim/approximate() (maybe with different names) * Maybe remove the parentheses from Rational.__str__() * Maybe rename one of the Rational classes * Maybe make Rational('3/2') work. ........ r59978 | andrew.kuchling | 2008-01-15 06:38:05 -0800 (Tue, 15 Jan 2008) | 8 lines Restore description of sys.dont_write_bytecode. The duplication is intentional -- this paragraph is in a section describing additions to the sys module, and there's a later section that mentions the switch. I think most people scan the what's-new and don't read it in detail, so a bit of duplication is OK. ........ r59984 | guido.van.rossum | 2008-01-15 09:59:29 -0800 (Tue, 15 Jan 2008) | 3 lines Issue #1786 (by myself): pdb should use its own stdin/stdout around an exec call and when creating a recursive instance. ........
This commit is contained in:
parent
ae138cbfbb
commit
7736b5becd
17 changed files with 997 additions and 436 deletions
|
@ -1,306 +0,0 @@
|
|||
'''\
|
||||
This module implements rational numbers.
|
||||
|
||||
The entry point of this module is the function
|
||||
rat(numerator, denominator)
|
||||
If either numerator or denominator is of an integral or rational type,
|
||||
the result is a rational number, else, the result is the simplest of
|
||||
the types float and complex which can hold numerator/denominator.
|
||||
If denominator is omitted, it defaults to 1.
|
||||
Rational numbers can be used in calculations with any other numeric
|
||||
type. The result of the calculation will be rational if possible.
|
||||
|
||||
There is also a test function with calling sequence
|
||||
test()
|
||||
The documentation string of the test function contains the expected
|
||||
output.
|
||||
'''
|
||||
|
||||
# Contributed by Sjoerd Mullender
|
||||
|
||||
from types import *
|
||||
|
||||
def gcd(a, b):
|
||||
'''Calculate the Greatest Common Divisor.'''
|
||||
while b:
|
||||
a, b = b, a%b
|
||||
return a
|
||||
|
||||
def rat(num, den = 1):
|
||||
# must check complex before float
|
||||
if isinstance(num, complex) or isinstance(den, complex):
|
||||
# numerator or denominator is complex: return a complex
|
||||
return complex(num) / complex(den)
|
||||
if isinstance(num, float) or isinstance(den, float):
|
||||
# numerator or denominator is float: return a float
|
||||
return float(num) / float(den)
|
||||
# otherwise return a rational
|
||||
return Rat(num, den)
|
||||
|
||||
class Rat:
|
||||
'''This class implements rational numbers.'''
|
||||
|
||||
def __init__(self, num, den = 1):
|
||||
if den == 0:
|
||||
raise ZeroDivisionError('rat(x, 0)')
|
||||
|
||||
# normalize
|
||||
|
||||
# must check complex before float
|
||||
if (isinstance(num, complex) or
|
||||
isinstance(den, complex)):
|
||||
# numerator or denominator is complex:
|
||||
# normalized form has denominator == 1+0j
|
||||
self.__num = complex(num) / complex(den)
|
||||
self.__den = complex(1)
|
||||
return
|
||||
if isinstance(num, float) or isinstance(den, float):
|
||||
# numerator or denominator is float:
|
||||
# normalized form has denominator == 1.0
|
||||
self.__num = float(num) / float(den)
|
||||
self.__den = 1.0
|
||||
return
|
||||
if (isinstance(num, self.__class__) or
|
||||
isinstance(den, self.__class__)):
|
||||
# numerator or denominator is rational
|
||||
new = num / den
|
||||
if not isinstance(new, self.__class__):
|
||||
self.__num = new
|
||||
if isinstance(new, complex):
|
||||
self.__den = complex(1)
|
||||
else:
|
||||
self.__den = 1.0
|
||||
else:
|
||||
self.__num = new.__num
|
||||
self.__den = new.__den
|
||||
else:
|
||||
# make sure numerator and denominator don't
|
||||
# have common factors
|
||||
# this also makes sure that denominator > 0
|
||||
g = gcd(num, den)
|
||||
self.__num = num / g
|
||||
self.__den = den / g
|
||||
# try making numerator and denominator of IntType if they fit
|
||||
try:
|
||||
numi = int(self.__num)
|
||||
deni = int(self.__den)
|
||||
except (OverflowError, TypeError):
|
||||
pass
|
||||
else:
|
||||
if self.__num == numi and self.__den == deni:
|
||||
self.__num = numi
|
||||
self.__den = deni
|
||||
|
||||
def __repr__(self):
|
||||
return 'Rat(%s,%s)' % (self.__num, self.__den)
|
||||
|
||||
def __str__(self):
|
||||
if self.__den == 1:
|
||||
return str(self.__num)
|
||||
else:
|
||||
return '(%s/%s)' % (str(self.__num), str(self.__den))
|
||||
|
||||
# a + b
|
||||
def __add__(a, b):
|
||||
try:
|
||||
return rat(a.__num * b.__den + b.__num * a.__den,
|
||||
a.__den * b.__den)
|
||||
except OverflowError:
|
||||
return rat(int(a.__num) * int(b.__den) +
|
||||
int(b.__num) * int(a.__den),
|
||||
int(a.__den) * int(b.__den))
|
||||
|
||||
def __radd__(b, a):
|
||||
return Rat(a) + b
|
||||
|
||||
# a - b
|
||||
def __sub__(a, b):
|
||||
try:
|
||||
return rat(a.__num * b.__den - b.__num * a.__den,
|
||||
a.__den * b.__den)
|
||||
except OverflowError:
|
||||
return rat(int(a.__num) * int(b.__den) -
|
||||
int(b.__num) * int(a.__den),
|
||||
int(a.__den) * int(b.__den))
|
||||
|
||||
def __rsub__(b, a):
|
||||
return Rat(a) - b
|
||||
|
||||
# a * b
|
||||
def __mul__(a, b):
|
||||
try:
|
||||
return rat(a.__num * b.__num, a.__den * b.__den)
|
||||
except OverflowError:
|
||||
return rat(int(a.__num) * int(b.__num),
|
||||
int(a.__den) * int(b.__den))
|
||||
|
||||
def __rmul__(b, a):
|
||||
return Rat(a) * b
|
||||
|
||||
# a / b
|
||||
def __div__(a, b):
|
||||
try:
|
||||
return rat(a.__num * b.__den, a.__den * b.__num)
|
||||
except OverflowError:
|
||||
return rat(int(a.__num) * int(b.__den),
|
||||
int(a.__den) * int(b.__num))
|
||||
|
||||
def __rdiv__(b, a):
|
||||
return Rat(a) / b
|
||||
|
||||
# a % b
|
||||
def __mod__(a, b):
|
||||
div = a / b
|
||||
try:
|
||||
div = int(div)
|
||||
except OverflowError:
|
||||
div = int(div)
|
||||
return a - b * div
|
||||
|
||||
def __rmod__(b, a):
|
||||
return Rat(a) % b
|
||||
|
||||
# a ** b
|
||||
def __pow__(a, b):
|
||||
if b.__den != 1:
|
||||
if isinstance(a.__num, complex):
|
||||
a = complex(a)
|
||||
else:
|
||||
a = float(a)
|
||||
if isinstance(b.__num, complex):
|
||||
b = complex(b)
|
||||
else:
|
||||
b = float(b)
|
||||
return a ** b
|
||||
try:
|
||||
return rat(a.__num ** b.__num, a.__den ** b.__num)
|
||||
except OverflowError:
|
||||
return rat(int(a.__num) ** b.__num,
|
||||
int(a.__den) ** b.__num)
|
||||
|
||||
def __rpow__(b, a):
|
||||
return Rat(a) ** b
|
||||
|
||||
# -a
|
||||
def __neg__(a):
|
||||
try:
|
||||
return rat(-a.__num, a.__den)
|
||||
except OverflowError:
|
||||
# a.__num == sys.maxint
|
||||
return rat(-int(a.__num), a.__den)
|
||||
|
||||
# abs(a)
|
||||
def __abs__(a):
|
||||
return rat(abs(a.__num), a.__den)
|
||||
|
||||
# int(a)
|
||||
def __int__(a):
|
||||
return int(a.__num / a.__den)
|
||||
|
||||
# long(a)
|
||||
def __long__(a):
|
||||
return int(a.__num) / int(a.__den)
|
||||
|
||||
# float(a)
|
||||
def __float__(a):
|
||||
return float(a.__num) / float(a.__den)
|
||||
|
||||
# complex(a)
|
||||
def __complex__(a):
|
||||
return complex(a.__num) / complex(a.__den)
|
||||
|
||||
# cmp(a,b)
|
||||
def __cmp__(a, b):
|
||||
diff = Rat(a - b)
|
||||
if diff.__num < 0:
|
||||
return -1
|
||||
elif diff.__num > 0:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
|
||||
def __rcmp__(b, a):
|
||||
return cmp(Rat(a), b)
|
||||
|
||||
# a != 0
|
||||
def __bool__(a):
|
||||
return a.__num != 0
|
||||
|
||||
def test():
|
||||
'''\
|
||||
Test function for rat module.
|
||||
|
||||
The expected output is (module some differences in floating
|
||||
precission):
|
||||
-1
|
||||
-1
|
||||
0 0L 0.1 (0.1+0j)
|
||||
[Rat(1,2), Rat(-3,10), Rat(1,25), Rat(1,4)]
|
||||
[Rat(-3,10), Rat(1,25), Rat(1,4), Rat(1,2)]
|
||||
0
|
||||
(11/10)
|
||||
(11/10)
|
||||
1.1
|
||||
OK
|
||||
2 1.5 (3/2) (1.5+1.5j) (15707963/5000000)
|
||||
2 2 2.0 (2+0j)
|
||||
|
||||
4 0 4 1 4 0
|
||||
3.5 0.5 3.0 1.33333333333 2.82842712475 1
|
||||
(7/2) (1/2) 3 (4/3) 2.82842712475 1
|
||||
(3.5+1.5j) (0.5-1.5j) (3+3j) (0.666666666667-0.666666666667j) (1.43248815986+2.43884761145j) 1
|
||||
1.5 1 1.5 (1.5+0j)
|
||||
|
||||
3.5 -0.5 3.0 0.75 2.25 -1
|
||||
3.0 0.0 2.25 1.0 1.83711730709 0
|
||||
3.0 0.0 2.25 1.0 1.83711730709 1
|
||||
(3+1.5j) -1.5j (2.25+2.25j) (0.5-0.5j) (1.50768393746+1.04970907623j) -1
|
||||
(3/2) 1 1.5 (1.5+0j)
|
||||
|
||||
(7/2) (-1/2) 3 (3/4) (9/4) -1
|
||||
3.0 0.0 2.25 1.0 1.83711730709 -1
|
||||
3 0 (9/4) 1 1.83711730709 0
|
||||
(3+1.5j) -1.5j (2.25+2.25j) (0.5-0.5j) (1.50768393746+1.04970907623j) -1
|
||||
(1.5+1.5j) (1.5+1.5j)
|
||||
|
||||
(3.5+1.5j) (-0.5+1.5j) (3+3j) (0.75+0.75j) 4.5j -1
|
||||
(3+1.5j) 1.5j (2.25+2.25j) (1+1j) (1.18235814075+2.85446505899j) 1
|
||||
(3+1.5j) 1.5j (2.25+2.25j) (1+1j) (1.18235814075+2.85446505899j) 1
|
||||
(3+3j) 0j 4.5j (1+0j) (-0.638110484918+0.705394566962j) 0
|
||||
'''
|
||||
print(rat(-1, 1))
|
||||
print(rat(1, -1))
|
||||
a = rat(1, 10)
|
||||
print(int(a), int(a), float(a), complex(a))
|
||||
b = rat(2, 5)
|
||||
l = [a+b, a-b, a*b, a/b]
|
||||
print(l)
|
||||
l.sort()
|
||||
print(l)
|
||||
print(rat(0, 1))
|
||||
print(a+1)
|
||||
print(a+1)
|
||||
print(a+1.0)
|
||||
try:
|
||||
print(rat(1, 0))
|
||||
raise SystemError('should have been ZeroDivisionError')
|
||||
except ZeroDivisionError:
|
||||
print('OK')
|
||||
print(rat(2), rat(1.5), rat(3, 2), rat(1.5+1.5j), rat(31415926,10000000))
|
||||
list = [2, 1.5, rat(3,2), 1.5+1.5j]
|
||||
for i in list:
|
||||
print(i, end=' ')
|
||||
if not isinstance(i, complex):
|
||||
print(int(i), float(i), end=' ')
|
||||
print(complex(i))
|
||||
print()
|
||||
for j in list:
|
||||
print(i + j, i - j, i * j, i / j, i ** j, end=' ')
|
||||
if not (isinstance(i, complex) or
|
||||
isinstance(j, complex)):
|
||||
print(cmp(i, j))
|
||||
print()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test()
|
Loading…
Add table
Add a link
Reference in a new issue