#!/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'Absolute Error')
P.grid()
# Display the actual plot
P.show()