Exact Real Arithmetic in Python
Marcin Ciura
Google Poland Kraków, May 12, 2011
Marcin Ciura Google Poland Krakw, May 12, 2011 Reals in Python - - PowerPoint PPT Presentation
Exact Real Arithmetic in Python Marcin Ciura Google Poland Krakw, May 12, 2011 Reals in Python float , math IEEE 754 double arithmetic built-in type, standard library Reals in Python decimal.Decimal decimal floating-point
Google Poland Kraków, May 12, 2011
◮ IEEE 754 double arithmetic ◮ built-in type, standard library
◮ decimal floating-point arithmetic ◮ since Python 2.4
◮ multiple-precision arithmetic ◮ third-party library
logistic map x0 = 0.671875 xn+1 = 4xn(1 − xn)
n exact decimal gmpy.mpf float 0.671875 0.671875 0.671875 0.671875 1 0.881835 0.881835 0.881835 0.881835 2 0.416805 0.416805 0.416805 0.416805 3 0.972314 0.972314 0.972314 0.972314 4 0.107675 0.107675 0.107675 0.107675
n exact decimal gmpy.mpf float 53 0.717980 0.717980 0.717980 0.749943 54 0.809938 0.809938 0.809937 0.750112 55 0.615751 0.615751 0.615755 0.749775 56 0.946406 0.946406 0.946403 0.750449 57 0.202886 0.202886 0.202897 0.749100
n exact decimal gmpy.mpf float 68 0.910298 0.910298 0.893725 0.000935 69 0.326622 0.326622 0.379919 0.003740 70 0.879760 0.879760 0.942322 0.014904 71 0.423127 0.423127 0.217403 0.058727 72 0.976362 0.976362 0.680555 0.221116
n exact decimal gmpy.mpf float 91 0.035427 0.023866 0.241684 0.487988 92 0.136690 0.093186 0.733092 0.999422 93 0.472024 0.338009 0.782670 0.002306 94 0.996869 0.895036 0.680388 0.009206 95 0.012483 0.375783 0.869839 0.036486
◮ float ◮ decimal.Decimal ◮ gmpy.mpf
round-off errors (begot numerical analysis) fast
◮ continued fractions ◮ scaled integers ◮ Möbius transformations ◮ other methods
no round-off errors slowish
◮ Introduction
◮ Continued fractions ◮ Gosper’s algorithm ◮ Python implementation ◮ Live demo
a0 + 1 a1 + 1 a2 + 1 a3 + 1 ... ak partial quotients [a0; a1, a2, a3, . . . , ak]
byproduct of Euclid’s gcd algorithm 96 = 1 × 65 + 31 65 = 2 × 31 + 3 31 = 10 × 3 + 1 3 = 3 × 1 96 65 = [1; 2, 10, 3]
◮ 1 : 1 correspondence with reals ◮ finite c.f. – rationals ◮ infinite c.f. – irrationals ◮ truncated c.f. – best approximations ◮ usually ∼ 0.97027 partial quotients per digit
(e.g. 971 p.q. for initial 1000 digits of π)
quadratic irrationals – periodic c.f. √ 2 = [1; 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, . . .] − √ 2 = [−2; 1, 1, 2, 2, 2, 2, 2, 2, 2, . . .] √ 3 = [1; 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, . . .]
e1/n and tan(1/n) – patterns in c.f. e = [2; 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, . . .] e1/2 = [1; 1, 1, 1, 5, 1, 1, 9, 1, 1, 13, . . .] tan(1/2) = [0; 1, 1, 4, 1, 8, 1, 12, 1, 16, . . .]
π = [3; 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, . . .]
3
√ 2 = [1; 3, 1, 5, 1, 1, 4, 1, 1, 8, 1, 14, . . .]
◮ Gosper, 1972: +, −, ×, / ◮ Newton, 1671:
√
◮ Brouncker, 1656: π ◮ Ciura, 2007: tan, arctan, exp, log
bihomographic function z(x, y) = axy + bx + cy + d exy + fx + gy + h =
e f g h
special cases of bihomographic function x + y = 0xy + 1x + 1y + 0 0xy + 0x + 0y + 1 x − y = 0xy + 1x − 1y + 0 0xy + 0x + 0y + 1 xy = 1xy + 0x + 0y + 0 0xy + 0x + 0y + 1 x/y = 0xy + 1x + 0y + 0 0xy + 0x + 1y + 0
lazy evaluation of bihomographic function if [redacted] then emit r and change coeffs to
f g h a − er b − fr c − gr d − hr
change coeffs to
g + ep h + fp e f
change coeffs to
f + eq e h + gq g
+ π [ ] √ 2 [ ]
0 0 0 1
+ π [3] √ 2 [ ]
0 1 0 0
3
+ π [3; 7] √ 2 [ ]
7 0 1
7
+ π [3; 7] √ 2 [1]
7 0 1 0
1
+ π [3; 7] √ 2 [1; 2]
14 7 2 1
2
+ π [3; 7] √ 2 [1; 2]
9 1 1 0
4
+ π [3; 7] √ 2 [1; 2, 2]
19 9 2 1
2
+ π [3; 7, 15] √ 2 [1; 2, 2]
287 136 19 9
15
+ π [3; 7, 15] √ 2 [1; 2, 2]
243 76 16 5
1
+ π [3; 7, 15] √ 2 [1; 2, 2]
44 60 3 4
1
+ π [3; 7, 15] √ 2 [1; 2, 2, 2]
148 44 10 3
2
+ π [3; 7, 15] √ 2 [1; 2, 2, 2, 2]
340 148 23 10
2
+ π [3; 7, 15] √ 2 [1; 2, 2, 2, 2, 2]
828 340 56 23
2
+ π [3; 7, 15, 1] √ 2 [1; 2, 2, 2, 2, 2]
884 363 828 340
1
+ π [3; 7, 15, 1] √ 2 [1; 2, 2, 2, 2, 2, 2]
2131 884 1996 828
2
+ π [3; 7, 15, 1] √ 2 [1; 2, 2, 2, 2, 2, 2]
2090 861 1971 812
3
+ π [3; 7, 15, 1] √ 2 [1; 2, 2, 2, 2, 2, 2]
41 23 25 16
1
+ π [3; 7, 15, 1, . . .] √ 2 [1; 2, 2, 2, 2, 2, 2, . . .]
[4; 1, 1, 3, 1, . . .]
× √ 2 [ ] √ 2 [ ]
0 0 0 1
× √ 2 [1] √ 2 [ ]
0 1 0 0
1
× √ 2 [1] √ 2 [1]
1 0 0 0
1
× √ 2 [1] √ 2 [1; 2]
2 1 0 0
2
× √ 2 [1; 2] √ 2 [1; 2]
4 2 2 1
2
× √ 2 [1; 2] √ 2 [1; 2, 2]
10 4 5 2
2
× √ 2 [1; 2, 2] √ 2 [1; 2, 2]
25 10 10 4
2
× √ 2 [1; 2, 2] √ 2 [1; 2, 2, 2]
60 25 24 10
2
× √ 2 [1; 2, 2, 2] √ 2 [1; 2, 2, 2]
144 60 60 25
2
× √ 2 [1; 2, 2, 2] √ 2 [1; 2, 2, 2, 2]
348 144 145 60
2
× √ 2 [1; 2, 2, 2, 2] √ 2 [1; 2, 2, 2, 2]
841 348 348 144
2
× √ 2 [1; 2, 2, 2, 2] √ 2 [1; 2, 2, 2, 2, 2]
2030 841 840 348
2
× √ 2 [1; 2, 2, 2, 2, 2] √ 2 [1; 2, 2, 2, 2, 2]
4900 2030 2030 841
2
× √ 2 [1; 2, 2, 2, 2, 2] √ 2 [1; 2, 2, 2, 2, 2, 2]
11830 4900 4901 2030
2
× √ 2 [1; 2, 2, 2, 2, 2, 2] √ 2 [1; 2, 2, 2, 2, 2, 2]
28561 11830 11830 4900
2
× √ 2 [1; 2, 2, 2, 2, 2, 2] √ 2 [1; 2, 2, 2, 2, 2, 2]
[2] 2
× √ 2 [1; 2, 2, 2, 2, 2, 2] √ 2 [1; 2, 2, 2, 2, 2, 2]
[2; ∞] ∞
◮ irrational arguments, rational result –
undecidable
◮ give up after 100 resultless iterations ◮ risk of incorrect result at most
1.5 × 10−31 × number of partial quotients
◮ integer bignums ◮ lazy evaluation ◮ garbage collection
◮ long type ◮ generators ◮ garbage collection
◮ source generators: c.f. for rational numbers,
canned sequences of p.q., and π
◮ intermediate generators: bihomographic
function, homographic function, exp, log, tan, atan, and sqrt
◮ sinks: type conversions, __cmp__, __str__,
and __repr__
◮ functions and methods return (chained)
generators
0 2
1 0 0 1
◮ calling a sink makes it request p.q. from its
inputs, they request p.q. from theirs, etc.
◮ generated partial quotients are cached
◮ cf.cf ◮ http://tnij.org/continued-fractions/ ◮ 2000 lines of Python ◮ function parity with math
>>> (sqrt(2) - 1) * (sqrt(2) + 1) 1.
>>> sqrt(5 + 2*sqrt(6)) == sqrt(2) + sqrt(3) True
>>> [sin(x)**2 + cos(x)**2 for x in ... [pi * random.random(), ... pi * random.random(), ... pi * random.random()]] [1., 1., 1.]
>>> [cos(3*x)/cos(x) == ... cos(x)**2 - 3*sin(x)**2 for x in ... [pi * random.random(), ... pi * random.random(), ... pi * random.random()]] [True, True, True]
>>> [x == x + cf(10)**-1000 for x in ... [cf(random.random()), ... cf(random.random()), ... cf(random.random())]] [False, False, False]
>>> sqrt(2) == sqrt(2) + cf(10)**-1000 True
◮ chaos theory ◮ computational geometry ◮ computational number theory ◮ educational applications