1:#!/usr/bin/python
   2:import math
   3:
   4:
   5:def preciseAcot(value, scale):
   6:    """This function calculates the arc cotan of a value scaled by the scale 
   7:    factor. It uses long integer arithmetic to get more precision."""
   8:    n = 1
   9:    term = preciseAcotTerm(value, 1, scale)
  10:    sumTerms = 0
  11:    while (abs(term) >= 1):
  12:        sumTerms += term
  13:        n += 1
  14:        term = preciseAcotTerm(value, n, scale)
  15:    return sumTerms
  16:
  17:
  18:def preciseAcotTerm(value, n, scale):
  19:    if ( n % 2 ) == 0:
  20:        sign = -1
  21:    else:
  22:        sign = 1    
  23:    numerator = (sign * scale)
  24:    denominator = ((value ** ((2 * n) - 1)) * ((2 * n) - 1))
  25:    retVal = numerator // denominator
  26:    return retVal
  27:
  28:    
  29:def evenFibonacci():
  30:    """ An unbounded generator for the even terms (F2, F4, F6, etc.) of the 
  31:    Fibonacci sequence. Based upon recipe 19.3, by Tom Good and Leandro Mariano 
  32:    Lopez, from the Python Cookbook. The sequence starts from F2."""
  33:    F_odd, F_even = 1, 2
  34:    while True:
  35:        yield F_even
  36:        F_odd  = F_odd + F_even
  37:        F_even = F_odd + F_even
  38:
  39:
  40:def sumExpansion(scale):
  41:    # This function sums up the arc cotan function values of the even terms 
  42:    # in the Fibonacci sequence to produce an approximation of pi/4
  43:    evenFiboGen = evenFibonacci()
  44:    Fn = evenFiboGen.next()
  45:    term = preciseAcot(Fn, scale)
  46:    sumTerms = 0L
  47:    while (abs(term) >= 1):
  48:        sumTerms += term
  49:        Fn = evenFiboGen.next() 
  50:        term = preciseAcot(Fn, scale)
  51:    return sumTerms
  52:
  53:
  54:def calculatePi(precision):
  55:    # Add a couple of extra decimal places to the precision to take rounding 
  56:    # error of terms in the expansion into account. Scale back down for the 
  57:    # output.
  58:    extraDigits = ( long(math.ceil(math.log10(precision * 30))) + 1)
  59:    scale = pow(10, (precision + extraDigits))  
  60:    piDigits = 4 * sumExpansion(scale)
  61:    return piDigits // pow(10, extraDigits)
  62:
  63:
  64:if __name__ == "__main__":
  65:    import sys
  66:    precision = int(sys.argv[1])
  67:    print "Hello world. Here are", precision,"digits of pi:\n", calculatePi(precision)