Menu

[r3300]: / trunk / py4science / examples / wallis_pi.py  Maximize  Restore  History

Download this file

107 lines (80 with data), 2.7 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
#!/usr/bin/env python
"""Simple demonstration of Python's arbitrary-precision integers."""
# We need exact division between integers as the default, without manual
# conversion to float b/c we'll be dividing numbers too big to be represented
# in floating point.
from __future__ import division
def pi(n):
"""Compute pi using n terms of Wallis' product.
Wallis' formula approximates pi as
pi(n) = 2 \prod_{i=1}^{n}\frac{4i^2}{4i^2-1}."""
num = 1
den = 1
for i in xrange(1,n+1):
tmp = 4*i*i
num *= tmp
den *= tmp-1
return 2.0*(num/den)
def part_range(n1,n2,nchunks):
"""Partition a range specification in nchunks"""
size,rem = divmod(n2-n1,nchunks)
sizes = [size]*nchunks
while rem > 0:
for i in range(nchunks):
sizes[i] += 1
rem -= 1
if rem == 0:
break
# The sizes list has the offsets, now we need the actual start,stop pairs
ranges = []
start=n1
for size in sizes:
ranges.append((start,start+size))
start += size
return ranges
def wpi_nd(range_spec):
"""Compute pi using n terms of Wallis' product.
Wallis' formula approximates pi as
pi(n) = 2 \prod_{i=1}^{n}\frac{4i^2}{4i^2-1}."""
n1,n2 = range_spec
num = 1
den = 1
for i in xrange(n1,n2):
tmp = 4*i*i
num *= tmp
den *= tmp-1
return num,den
def par_pi(n,num_engines=1):
"""Compute pi using n terms of Wallis' product.
Wallis' formula approximates pi as
pi(n) = 2 \prod_{i=1}^{n}\frac{4i^2}{4i^2-1}.
Parallel version."""
num,den = reduce(lambda x,y:(x[0]*y[0],x[1]*y[1]),
map(wpi_nd,part_range(1,n+1,num_engines)))
return 2.0*(num/den)
# This part only executes when the code is run as a script, not when it is
# imported as a library
if __name__ == '__main__':
# Simple convergence demo.
# A few modules we need
import pylab as P
import numpy as N
# Create a list of points 'nrange' where we'll compute Wallis' formula
nrange = N.linspace(10,2000,20).astype(int)
# Make an array of such values
wpi = N.array(map(pi,nrange))
# Compute the difference against the value of pi in numpy (standard
# 16-digit value)
diff = abs(wpi-N.pi)
# Make a new figure and build a semilog plot of the difference so we can
# see the quality of the convergence
P.figure()
# Line plot with red circles at the data points
P.semilogy(nrange,diff,'-o',mfc='red')
# A bit of labeling and a grid
P.title(r"Convergence of Wallis' product formula for $\pi$")
P.xlabel('Number of terms')
P.ylabel(r'|Error|')
P.grid()
# Display the actual plot
P.show()