Leibniz_Pi.py
Bengt Richter
bokr at oz.net
Sat Oct 12 03:14:45 EDT 2002
On Fri, 11 Oct 2002 10:14:38 -0700, "Cousin Stanley" <CousinStanley at HotMail.com> wrote:
>Yesterday in the news group comp.lang.java.help
>I found a Java example of the Leibniz Pi approximation
>and converted the Java code to Python ...=20
>
>The numerical results from either version=20
>using a LARGE number of terms as a program argument
>provide approximations for the number Pi that seems correct ...=20
>
>Using 1 million terms as an input argument,
>the Java version is a bit faster, which I think
>is expected ...=20
>
> On a 250 MHz Win98 machine ...=20
> =20
> Java SDK 1.4 ....... ~ 3-4 seconds
> Python 2.2.1 ......... ~ 9-10 seconds
>
>Since I am fairly new to BOTH Java AND Python,
>I'm wondering if there are any ...=20
>
> obvious oversights ???
> Python improvements ???
>
>Python code follows ...
>
>Cousin Stanley
>
>----------------------------------------------------------------
>
>'''=20
> Leibniz_Pi.py
>
> Pi =3D 4 * ( 1 - 1/3 + 1/5 - 1/7 + 1/9 - 1/11 + 1/13 - 1/15 ... )
>
> Using one million terms provides a good approximation ...
>
> Posted to the NewsGroup
> comp.lang.java.help 2002-10-10=20
> By Jonas Lindstr=F6m
>
> Converted to Python
> By Stanley C. Kitching
>'''
>
>import sys
>print '\n Approximate Pi via Leibniz Sequence '
>
>def calculate_pi( nTerms ) :
>
> limit =3D ( 2 * nTerms ) - 1=20
>
> if ( ( limit - 1 ) % 4 ) =3D=3D 0 : =20
> sign =3D +1.0=20
> else :=20
> sign =3D -1.0
>
> sum =3D 0.0
>
> for i in range( limit , 0 , -2 ) :=20
> sum +=3D sign / i
> sign =3D -sign
>
> return 4.0 * sum=20
>
>nTerms =3D int( sys.argv[ 1 ] )=20
>
>Pi =3D calculate_pi( nTerms )
>
>print '\n Terms : ' , nTerms
>print '\n Pi : ' , Pi
>
>
[ 0:01] C:\pywk\pi>pisigint.py
(Type Ctrl-C to stop generating pi)
50 4085.12 dig/sec 31415926535897932384626433832795028841971693993751
100 3292.99 dig/sec 05820974944592307816406286208998628034825342117067
150 2422.61 dig/sec 98214808651328230664709384460955058223172535940812
200 1851.27 dig/sec 84811174502841027019385211055596446229489549303819
250 1473.79 dig/sec 64428810975665933446128475648233786783165271201909
300 1277.74 dig/sec 14564856692346034861045432664821339360726024914127
350 1087.28 dig/sec 37245870066063155881748815209209628292540917153643
400 1003.15 dig/sec 67892590360011330530548820466521384146951941511609
450 852.50 dig/sec 43305727036575959195309218611738193261179310511854
500 742.55 dig/sec 80744623799627495673518857527248912279381830119491
550 666.12 dig/sec 29833673362440656643086021394946395224737190702179
600 624.75 dig/sec 86094370277053921717629317675238467481846766940513
650 595.61 dig/sec 20005681271452635608277857713427577896091736371787
700 535.77 dig/sec 21468440901224953430146549585371050792279689258923
750 501.08 dig/sec 54201995611212902196086403441815981362977477130996
800 470.28 dig/sec 05187072113499999983729780499510597317328160963185
850 436.58 dig/sec 95024459455346908302642522308253344685035261931188
900 333.36 dig/sec 17101000313783875288658753320838142061717766914730
950 363.52 dig/sec 35982534904287554687311595628638823537875937519577
818577805321712
965 Total digits
(965 total digits)
(I hit Ctrl-C fairly shortly).
You can redirect the pi digits, and watch the left part on a single line
being rewritten, which looks like so:
[ 0:10] C:\pywk\pi>python pisigint.py >zz.txt
(Type Ctrl-C to stop generating pi)
2455 Total digits
[ 0:10] C:\pywk\pi>
----< pisigint.py >-------------------------
#!/usr/bin/python
# Print digits of pi forever, unless you hit Ctrl-C
# The output is split between stderr and stdout so that you can
# redirect the pi digits to a file, like so
# python pisiginit.py > pidigits.txt
# and still see how many and how fast digits are being output. The latter
# info is rewritten without \n, so it does not scroll. If you don't
# redirect you see the latter to the left and the pi digits 50 at a time
# to the right. This is a modified version of the algorithm as found
# somewhere on the Ruby site.
#
# The algorithm, using Python's 'long' integers ("bignums"), works
# with continued fractions, and was conceived by Lambert Meertens.
#
# See also the ABC Programmer's Handbook, by Geurts, Meertens & Pemberton,
# published by Prentice-Hall (UK) Ltd., 1990.
import sys, signal
from time import clock
class SigHandler:
def __init__(self):
self.signaled = 0
def __call__(self, sn, sf):
self.signaled += 1
sh = SigHandler()
oldHandler = signal.signal(signal.SIGINT,sh)
k, a, b, a1, b1 = 2L, 4L, 1L, 12L, 4L
digits=0 # count to show progress
lines = 0
digline = []
start=clock()
sys.__stderr__.write('\r(Type Ctrl-C to stop generating pi)\n')
while not sh.signaled:
# Next approximation
p, q, k = k*k, 2*k+1, k+1
a, b, a1, b1 = a1, b1, p*a+q*a1, p*b+q*b1
# Print common digits
d = a / b
d1 = a1 / b1
while d == d1:
digits += 1
#sys.__stderr__.write('\r%5d' % (digits,))
digline.append(d)
if len(digline)==50:
sys.__stderr__.write('\r%5d %8.2f dig/sec ' % (digits, 50.0/(clock()-start)))
lines += 1
print ''.join(map(lambda x: chr(x+48),digline))
digline = []
start=clock()
a, a1 = 10*(a%b), 10*(a1%b1)
d, d1 = a/b, a1/b1
sys.__stderr__.write('\r'+' '*24)
if digline: print ''.join(map(lambda x: chr(x+48),digline))
sys.__stderr__.write('\r%5d Total digits \n'% (lines*50+len(digline)))
print '\n(%d total digits)' % (lines*50+len(digline))
signal.signal(signal.SIGINT,oldHandler)
--------------------------------------------
Regards,
Bengt Richter
More information about the Python-list
mailing list