My first Python program.. Calculating pi geometrically.
Ron Adam
radam2 at tampabay.rr.com
Sat Nov 1 07:49:55 CET 2003
Hi, I'm having fun learning Python and want to say thanks to everyone
here for a great programming language.
Below is my first Python program (not my first program) and I'd
apreciate any feedback on how I might do things differently to make it
either more consice, readable, or faster. ie... are there better ways
to do it in Python?
It won't break any records for calculating pi, that wasn't my goal,
learning Python was. But it might be good for testing floating point
and decimal performance. It also might make a good demo of the same.
Anyway, here it is, any feedback would be apreciated.
_Ron
"""
## Program name: pi10.py
## Author: Ronald R. Adam
## Version: 1.01
## Date: 11/01/2003
##
## Email: radam2 at tampabay.rr.com or ron at ronadam.com
##
## This program calculates Pi using a geometric progression of
## triangles. The program is written in Python and requires
## the gmpy math module in order to use extended floating point
## precision.
##
## This is a rough diagram of the location of the points used.
##
## |
## A* --.__
## | \ `-._
## | \ `* D
## | \ / \
## | C * \
## | . \ \
## | . \ |
## | . \ |
## *---------------*---
## O B
##
## Pint C is the mid point of line AB.
## Point D is on the circle 90 degrees to line AB from point C.
##
## Area = OAB*4 + CDB*8 + ...
##
## ... Point A is relocated to point D and then new points
## C and D are calculated. This is repeated ...
##
## ... + CDB*16 + CDB*32 + ... (Repeats until done)
##
## When it's done, the last line of AB length multiplied by with
## the number of sides (2^n) is used to calculate the
## circumference, and then calculate pi again to check the result.
##
## Pi to 10,000 digits take about 5 minutes on my desktop computer.
## I'm not sure what the maximum is so drop me an email if you get
## some really long sequences. This program progrssivly slows down
## as the number of digits increases because it uses the entire
## length of each floating point number.
"""
import gmpy
import datetime
import time
print """
Pi10.py Version 1.0, by Ronald R. Adam
This program calculates Pi by using a geometric progression
of triangles to measure the area of a circle with a radius of 1.
"""
d=1
while d>0:
try:
d = gmpy.mpz(raw_input('Number of decimal digits: '))
except:
break
# Estimate the precision needed.
# This may need some adjustment.
p = int(d*3.325)+16 # gmpy precision value
start = time.clock()
t_old = start
print 'Calculating Pi ...'
# set variable values and precision.
n = gmpy.mpz('2') # number of triangles
radius = gmpy.mpf('1.0',p) # radius
area = gmpy.mpf((radius*radius)/2 * 2**n) #area=(base*height)/2*4
Ax, Ay = gmpy.mpf('0.0',p) , radius # point A
Bx, By = radius , gmpy.mpz('0') # point B
Cx = Cy = gmpy.mpf('0.0',p) # point C
OC = CD = CB = gmpy.mpf('0.0',p) # lines OC,CD,CB
vx = vy = gmpy.mpf('0.0',p) # vectors of line CD
# Loop until additions to area are too small to calculate
# using the requested precision + 2 digits.
p_area = gmpy.mpf('0.0',p)
while gmpy.fdigits(p_area,10,d+2) <> gmpy.fdigits(area,10,d+2):
p_area = area
Cx, Cy = (Ax+1)/2, Ay/2 # find midpoint of line AB
OC = gmpy.fsqrt(Cx**2 + Cy**2) # find length of line OC
CD = radius - OC # find length of line CD
CB = gmpy.fsqrt((Bx-Cx)**2+Cy**2) # find length of line CB
n += 1 # double triangles 2^(n+1)
area = area + (CB*CD/2) * 2**n # add trianges BCD * 2^n
vx = CD * Cx/OC # find x vector of line CD
vy = CD * Cy/OC # find y vector of line CD
Ax, Ay = Cx+vx, Cy+vy # Ax,Ay = Dx,Dy
t = time.clock()
if t > t_old+10:
t_old = t
print 'Exceeding 2^', n ,'sides ...'
# pi1 = area/radius^2
pi1 = gmpy.fdigits(area) # use (area/radius**2) if radius <>1
# pi2 = circumference /(2*radius)
pi2=gmpy.fdigits((gmpy.fsqrt((Bx-Ax)**2+(By-Ay)**2)*2**n)/(2*radius))
# Compare the two above calculations to each other
# and copy the matching & requested digits to the
# result string.
pi = ''
k = 0
while pi1[k] == pi2[k]:
pi = pi+pi1[k]
k += 1
pi = pi[0:int(d+2)]
# Report the result
print
print 'Pi =\n',pi
print
print len(pi)-2, 'decimal places'
print 'Radius =', radius
print '2^', n, ' sides'
stop = time.clock()
print 'Elapsed time:',datetime.timedelta( 0, stop-start)
print
# End #
More information about the Python-list
mailing list