Special numbers/Computer programs to calculate pi

From testwiki
Revision as of 21:38, 12 October 2007 by imported>Mike's bot account (re-categorization for Subject: pages)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Calculating the digits of pi (Python 2.3)

This python program calculates the digits of pi.

Equality used

4π=1+13+45+97+169+2511+...

Sample Output

$ python pimaker.py
=======================================
Pi = 4 div 4/pi
 
V = lazy_rcf2cf of lazy_rcf_4onpi
A = lazy_decimal of ( lazy(4) lazy_div  V )
Now display value of A one digit at a time
3141592653589793238462643383279502884197169399375105
8209749445923078164062862089986280348253421170679821
4808651328230664709384460955058223172535940812848111
7450284102701938521105559644622948954930381964428810

Source Code

#!/usr/bin/python

from __future__ import division
import copy
import sys
from types import IntType,FloatType,LongType,ListType,TupleType,InstanceType,ClassType

# set error output to stdout instead
#__errout = sys.stderr
__errout = sys.stdout

#
# Define class contfrac
# Continued Fraction object version 1
#
class contfrac:

  def __init__(self,numerator,denominator=0,limit=256,epsilon=2e-9):
    self.classname="contfracv1"
    # if called by A=contfrac(3.1416)
    if denominator==0:
      if type(numerator)==IntType or type(numerator)==LongType:
        self.num=numerator
        self.den=1
        self.cf=[numerator]
      elif type(numerator)==FloatType:
        self.cf = decimal2contfrac(numerator,limit,epsilon)
        (self.num,self.den) = contfrac2rational(self.cf)
      elif type(numerator)==ListType:
        self.cf=copy.copy(numerator)
        self.num,self.den=contfrac2rational(numerator)
      elif is_contfrac(numerator):
        self.num=numerator.num
        self.den=numerator.den
        self.cf=copy.copy(numerator.cf)
      else:
        # if all else fails its the devil's number
        self.num=666
        self.den=1
        self.cf=[666] 
    # if called by A=(2,3)
    else:
      self.cf = rational2contfrac(long(numerator),long(denominator))
      (self.num,self.den) = contfrac2rational(self.cf)

  def __len__(self):
    return len(self.cf)



def lid(cfobj):
  return lazy_identity(cfobj)

#
# Define class lazy_identity
# Lazy connector for contfrac objects
#
class lazy_identity:

  def __init__(self,cf):
    self.classname="lazy_identity"
    self.cfobj=cf
    self.n=0
    self.a=0
    self.b=1
    self.c=1
    self.d=0

  def egest(self,debugflag=False):
    # First check if we can egest
    # if we can then egest a digit
    # otherwise loop until we can
    if debugflag : print >> __errout,"a=%d,b=%d,c=%d,d=%d" % (self.a,self.b,self.c,self.d) 
    while 1 :
      if self.c == 0 and self.d == 0 :
        break
      if self.c <> 0 and self.d <> 0 and (self.a//self.c) == (self.b//self.d) :
        if debugflag : print >> __errout,"We can egest"
        break
      # Now we must ingest one term from cfobj
      if debugflag : print >> __errout,"n=%d len(cfobj)=%d" % (self.n,len(self.cfobj))
      if self.n < len(self.cfobj) :
        p=self.cfobj.cf[self.n]
        if debugflag : print >> __errout,"term ingested is ",p
        self.n=self.n+1
        # Now calculate the new a,b,c,d
        self.a,self.b,self.c,self.d=self.b,self.a+self.b*p,self.d,self.c+self.d*p
      else :
        if debugflag : print >> __errout,"term ingested is INF"
        self.n=self.n+1
        self.a,self.b,self.c,self.d=self.b,self.b,self.d,self.d
      if debugflag : print >> __errout,"after ingestion a=%d,b=%d,c=%d,d=%d" % (self.a,self.b,self.c,self.d) 
    # out of the while loop
    if self.c== 0 and self.d == 0 :
      if debugflag : print >> __errout,"egest the number INF"
      return 'INF'
    else:
      q=self.a//self.c
      if debugflag : print >> __errout,"egest the number ",q
      # Now calculate the new a,b,c,d
      self.a,self.b,self.c,self.d=self.c,self.d,self.a-self.c*q,self.b-self.d*q
      if debugflag : print >> __errout,"after egestion a=%d,b=%d,c=%d,d=%d" % (self.a,self.b,self.c,self.d) 
      return q
      

#
# Define class lazy_rcf_4onpi
# Lazy connector for 4/pi in regular continued fractions format
# [(1,1),(3,4),(5,9),(7,16),(9,25),(11,36),...]
#        (2n+1,(n+1)^2)
#
class lazy_rcf_4onpi:

  def __init__(self):
    self.classname="lazy_rcf_4onpi"
    self.n=0

  def egest(self,debugflag=False):
    a=  self.n * 2 + 1
    b= (self.n + 1) * (self.n + 1)
    self.n = self.n + 1
    return (a,b)


#
# Define class lazy_rcf2cf
# Lazy connector for turning regular continued fractions
# into standardize continued fractions
#
class lazy_rcf2cf:

  def __init__(self,rcf):
    self.classname="lazy_rcf2cf"
    self.cfobj=rcf
    self.a=0
    self.b=1
    self.c=1
    self.d=0

  def egest(self,debugflag=False):
    # First check if we can egest
    # if we can then egest a digit
    # otherwise loop until we can
    if debugflag : print >> __errout,"a=%d,b=%d,c=%d,d=%d" % (self.a,self.b,self.c,self.d) 
    while 1 :
      if self.c == 0 and self.d == 0 :
        break
      if self.c <> 0 and self.d <> 0 and (self.a//self.c) == (self.b//self.d) :
        if debugflag : print >> __errout,"We can egest"
        break
      # Now we must ingest one term from cfobj
      (p,q)=self.cfobj.egest()
      if debugflag : print >> __errout,"term ingested is ",p
      # Now calculate the new a,b,c,d
      self.a,self.b,self.c,self.d=self.b*q,self.a+self.b*p,self.d*q,self.c+self.d*p
      if debugflag : print >> __errout,"after ingestion a=%d,b=%d,c=%d,d=%d" % (self.a,self.b,self.c,self.d) 
    # out of the while loop
    if self.c== 0 and self.d == 0 :
      if debugflag : print >> __errout,"egest the number INF"
      return 'INF'
    else:
      q=self.a//self.c
      if debugflag : print >> __errout,"egest the number ",q
      # Now calculate the new a,b,c,d
      self.a,self.b,self.c,self.d=self.c,self.d,self.a-self.c*q,self.b-self.d*q
      if debugflag : print >> __errout,"after egestion a=%d,b=%d,c=%d,d=%d" % (self.a,self.b,self.c,self.d) 
      return q
      

#
# Define class lazy_decimal
# Lazy connector for contfrac objects
#
class lazy_decimal:

  def __init__(self,lazycf):
    self.classname="lazy_decimal"
    self.cfobj=lazycf
    self.a=0
    self.b=1
    self.c=1
    self.d=0

  def egest(self,debugflag=False):
    # First check if we can egest
    # if we can then egest a digit
    # otherwise loop until we can
    if debugflag : print >> __errout,"a=%d,b=%d,c=%d,d=%d" % (self.a,self.b,self.c,self.d) 
    while 1 :
      if self.c == 0 and self.d == 0 :
        break
      if self.c <> 0 and self.d <> 0 and (self.a//self.c) == (self.b//self.d) :
        if debugflag : print >> __errout,"We can egest"
        break
      # Now we must ingest one term from cfobj
      p=self.cfobj.egest()
      if p == 'INF' :
        if debugflag : print >> __errout,"term ingested is INF"
        self.a,self.b,self.c,self.d=self.b,self.b,self.d,self.d
      else :
        if debugflag : print >> __errout,"term ingested is ",p
        # Now calculate the new a,b,c,d
        self.a,self.b,self.c,self.d=self.b,self.a+self.b*p,self.d,self.c+self.d*p
      if debugflag : print >> __errout,"after ingestion a=%d,b=%d,c=%d,d=%d" % (self.a,self.b,self.c,self.d) 
    # out of the while loop
    if self.c== 0 and self.d == 0 :
      if debugflag : print >> __errout,"egest the number INF"
      return 'INF'
    else:
      r=self.a//self.c
      if debugflag : print >> __errout,"egest the number ",r
      # Now calculate the new a,b,c,d
      self.a,self.b,self.c,self.d=self.c,self.d,self.a-self.c*r,self.b-self.d*r
      if debugflag : print >> __errout,"after egestion a=%d,b=%d,c=%d,d=%d" % (self.a,self.b,self.c,self.d) 
      # Now calculate the egestion of r2=0 and s2=10
      # new_a = c * s2
      # new_b = d * s2
      # new_c = a - c * r2
      # new_d = b - d * r2
      self.a,self.b,self.c,self.d=self.c*10,self.d*10,self.a,self.b 
      if debugflag : print >> __errout,"after renormalisation a=%d,b=%d,c=%d,d=%d" % (self.a,self.b,self.c,self.d) 
      return r
      

#
# Define class lazy_base
# Lazy base for lazy operators
#
class lazy_base:

  def egest(self,debugflag=False):
    # First check if we can egest
    # if we can then egest a term
    # otherwise loop until we can
    if debugflag : print >> __errout,"a=%d,b=%d,c=%d,d=%di,e=%d,f=%d,g=%d,h=%d" % (self.a,self.b,self.c,self.d,self.e,self.f,self.g,self.h) 
    while 1 :
      self.count= self.count + 1
      if self.e == 0 and self.f == 0 and self.g == 0 and self.h == 0 :
        # We need to return INF
        break
      if self.e <> 0 :
        Zoo= self.a // self.e
      else:
        Zoo='INF'
      if self.g <> 0 :
        Zoi= self.c // self.g
      else:
        Zoi='INF'
      if self.f <> 0 :
        Zio= self.b // self.f
      else:
        Zio='INF'
      if self.h <> 0 :
        Zii= self.d // self.h
      else:
        Zii='INF'
      if debugflag : print >> __errout,"Zoo=",Zoo," Zoi=",Zoi," Zio=",Zio," Zii=",Zii
      if Zoo <> 'INF' and Zoo == Zoi and Zoi == Zio and Zio == Zii :
        if debugflag : print >> __errout,"We can egest"
        break
      # Now we must decide which lazy input to ingest from
      if Zio == 'INF' or Zoo == 'INF' :
        alpha='INF'
      else:
        alpha=abs(Zio - Zoo)
      if Zoi == 'INF' or Zoo == 'INF' :
        beta='INF'
      else:
        beta=abs(Zoi - Zoo)
      if debugflag : print >> __errout,"alpha=",alpha," beta=",beta
      if alpha=='INF' and beta=='INF' :
        if self.count % 2 == 0 :
          target='X'
        else:
          target='Y'
      elif alpha=='INF' and beta<>'INF' :
        target='X'
      elif beta=='INF' and alpha<>'INF' :
        target='Y'
      elif alpha > beta :
        target='X'
      else :
        target='Y'
      # Now we must ingest one term from cfobj
      if target=='X' :
        p=self.X.egest()
        if p == 'INF' :
          if debugflag : print >> __errout,"term X ingested is INF"
          self.a,self.b,self.c,self.d,self.e,self.f,self.g,self.h=self.b,self.b,self.d,self.d,self.f,self.f,self.h,self.h
        else :
          if debugflag : print >> __errout,"term X ingested is ",p
          # Now calc the new a b c d e f g h 
          self.a,self.b,self.c,self.d,self.e,self.f,self.g,self.h=self.b,self.a + self.b*p,self.d,self.c + self.d * p,self.f,self.e + self.f * p,self.h,self.g + self.h*p
      else :
        p=self.Y.egest()
        if p == 'INF' :
          if debugflag : print >> __errout,"term Y ingested is INF"
          self.a,self.b,self.c,self.d,self.e,self.f,self.g,self.h=self.c,self.d,self.c,self.d,self.g,self.h,self.g,self.h
        else :
          if debugflag : print >> __errout,"term Y ingested is ",p
          # Now calc the new a b c d e f g h 
          self.a,self.b,self.c,self.d,self.e,self.f,self.g,self.h=self.c,self.d,self.a+self.c*p,self.b+self.d*p,self.g,self.h,self.e+self.g*p,self.f+self.h*p
      # After ingestion
      if debugflag : print >> __errout,"after ingestion a=%d,b=%d,c=%d,d=%d,e=%d,f=%d,g=%d,h=%d" % (self.a,self.b,self.c,self.d,self.e,self.f,self.g,self.h) 
    # out of the while loop
    if self.e == 0 and self.f == 0 and self.g == 0 and self.h == 0 :
      if debugflag : print >> __errout,"egest the number INF"
      return 'INF'
    else:
      if debugflag : print >> __errout,"egest the number ",Zoo
      # Now calculate the new a,b,c,d,e,f,g,h
      self.a,self.b,self.c,self.d,self.e,self.f,self.g,self.h=self.e,self.f,self.g,self.h,self.a-self.e*Zoo,self.b-self.f*Zoo,self.c-self.g*Zoo,self.d-self.h*Zoo
      if debugflag : print >> __errout,"after egestion a=%d,b=%d,c=%d,d=%d,e=%d,f=%d,g=%d,h=%d" % (self.a,self.b,self.c,self.d,self.e,self.f,self.g,self.h) 
      return Zoo
    

#
# Define class lazy_add
# Lazy addition for lazy objects
#
class lazy_add(lazy_base):

  def __init__(self,XX,YY):
    self.classname="lazy_add"
    self.count=0
    self.X=XX
    self.Y=YY
    self.a=0
    self.b=1
    self.c=1
    self.d=0
    self.e=1
    self.f=0
    self.g=0
    self.h=0


#
# Define class lazy_sub
# Lazy subtraction for lazy objects
#
class lazy_sub(lazy_base):

  def __init__(self,XX,YY):
    self.classname="lazy_sub"
    self.count=0
    self.X=XX
    self.Y=YY
    self.a=0
    self.b=1
    self.c=-1
    self.d=0
    self.e=1
    self.f=0
    self.g=0
    self.h=0


#
# Define class lazy_mul
# Lazy multiplication for lazy objects
#
class lazy_mul(lazy_base):

  def __init__(self,XX,YY):
    self.classname="lazy_mul"
    self.count=0
    self.X=XX
    self.Y=YY
    self.a=0
    self.b=0
    self.c=0
    self.d=1
    self.e=1
    self.f=0
    self.g=0
    self.h=0


#
# Define class lazy_div
# Lazy division for lazy objects
#
class lazy_div(lazy_base):

  def __init__(self,XX,YY):
    self.classname="lazy_div"
    self.count=0
    self.X=XX
    self.Y=YY
    self.a=0
    self.b=1
    self.c=0
    self.d=0
    self.e=0
    self.f=0
    self.g=1
    self.h=0



if __name__ == '__main__':
  print "======================================="
  print "Pi = 4 div 4/pi"
  print " "
  print "V = lazy_rcf2cf of lazy_rcf_4onpi"
  print "A = lazy_decimal of ( lazy(4) lazy_div  V )"
  print "Now display value of A one digit at a time"
  rpi=lazy_rcf_4onpi()
  V=lazy_rcf2cf(rpi)
  A=lazy_decimal(lazy_div(lid(contfrac(4)),V))
  while 1:
    digit=A.egest()
    sys.stdout.write(str(digit))
    sys.stdout.flush()
  

Also note a "recipe" for pi using the Decimal class: Recipes demonstrating Decimal class