Pi is a mathematical concept related to circles, geometry, and probably more.


Subpages

Notice: Pi/Real cosine function/Definition and Pi/Zero of cosine/Introduction/Section are two subpages to Pi that should not be deleted because they are transclusions to another learning resource. Please do not delete this page because it might help "protect" the subpages.

Learning resources

edit

Wikipedia

edit

External

edit

Calculaton of π

edit

Radians, the natural angle

edit
 
Diagram illustrating one radian of angular measurement.
Arc of circle (red curved line with arrows) with length equal to radius of circle subtends one radian at center.
In diagram above, length of radius = length of arc = 1.
One radian  

If you were a mathematician among the ancient Sumerians of the 3rd millennium BC and you were determined to define the angle that could be adopted as a standard to be used by all users of trigonometry, you would probably suggest the angle in an equilateral triangle. This angle is easily defined, easily constructed, easily understood and easily reproduced. It would be easy to call this angle the "natural" angle.

The numeral system used by the ancient Sumerians was Sexagesimal, also known as base 60, a numeral system with sixty as its base. In practice the natural angle could be divided into 60 parts, now called degrees, and each degree could be divided into 60 parts, now called minutes, and so on.

Three equilateral triangles fit neatly into a semi-circle, hence 180 degrees in a semi-circle.

We know that   Therefore,   should be   or one half of our concept of the natural angle.

Whatever the natural angle might be, it has existed for billions of years, but it has come to light only in recent times with invention of the calculus.

In mathematics, the arctangent series, traditionally called Gregory's series, is the Taylor series expansion at the origin of the arctangent function:

 

The following python code calculates   using Gregory's series:

# python code

r3 = 3 ** .5
x = r3/3

arctan_x = (
      x        -  x**3/3  +  x**5/5  -  x**7/7  +  x**9/9  - x**11/11 + x**13/13 - x**15/15 + x**17/17 - x**19/19
    + x**21/21 - x**23/23 + x**25/25 - x**27/27 + x**29/29 - x**31/31 + x**33/33 - x**35/35 + x**37/37 - x**39/39
    + x**41/41 - x**43/43 + x**45/45 - x**47/47 + x**49/49 - x**51/51 + x**53/53 - x**55/55 + x**57/57 - x**59/59
    + x**61/61 - x**63/63 + x**65/65 - x**67/67 + x**69/69
)

sx = 'arctan_x' ; print (sx, '=', eval(sx))
arctan_x = 0.5235987755982988

Our assessment of the natural angle as the angle in an equilateral triangle was a very reasonable guess.

However, the natural angle is the radian, the angle subtended at center of circle by an arc on the circumference equal to the radius.

Six times arctan_x   or the number of radians in a semi-circle:

# python code

sx = 'arctan_x * 6' ; print (sx, '=', eval(sx))
sx = '180/(arctan_x * 6)' ; print (sx, '=', eval(sx))
arctan_x * 6 = 3.141592653589793
180/(arctan_x * 6) = 57.29577951308232

  number of radians in semi-circle.

One radian   slightly less than  


Because the value   is fairly large, calculation of arctan_x above required 34 operations to produce result accurate to 16 places of decimals. The calculation did not converge quickly.

Python code below uses much smaller values of  , and calculation of arctan_x for precision of 1001 is quite fast.

tan(A/2)

edit
 
Graphical calculation of  .
 
 
 

In diagram:

Point   has coordinates  

Point   has coordinates  

Mid point of   has coordinates  

         


  •  
  •  

Implementation

edit

This section calculates five values of   using the following known values of  

Angle    
   
   
   
   
   

Values of   in table below are derived from the above values by using identity  :

Angle    
  0.00000_00000_91432_37995_4197.....089_03901_63759_3912
  0.00000_00000_73145_90396_3357.....211_97500_56173_0713
  0.00000_00000_60954_91996_9464.....024_32806_94580_0689
  0.00000_00000_54859_42797_2518.....791_30634_03540_9738
  0.00000_00000_97527_87195_1143.....736_60376_04724_6778
# python code

desired_precision = 1001
number_of_leading_zeroes = 10 # See below.

import decimal
dD = decimal.Decimal # decimal object is like float with (almost) infinite precision.
dgt = decimal.getcontext()

Precision = dgt.prec = desired_precision + 3  # Adjust as necessary.
Tolerance = dD("1e-" + str(Precision-2))      # Adjust as necessary.
adjustment_to_precision = number_of_leading_zeroes * 2 + 3

def tan_halfA(tan_A) :
    dgt.prec += adjustment_to_precision
    top = -1 + (1+tan_A**2).sqrt()
    dgt.prec -= adjustment_to_precision
    tan_A_2 = top/tan_A
    return tan_A_2
    
def tan_2A (tanA) :
    '''
          2 * tanA
tan(2A) = -----------
          1 - tanA**2
    '''
    if tanA in (1,-1) : return '1/0'
    dgt.prec += adjustment_to_precision
    bottom = (1 - tanA**2)
    output = 2*tanA/bottom
    dgt.prec -= adjustment_to_precision
    return output+0

def θ_tanθ_from_A_tanA (angleA, tanA) :
    '''
if input == 45,1
output is:
"dD(45) / (2 ** (33))", "0.00000_00000_91432_37995_....._63759_3912"
                           ^^^^^^^^^^^
number_of_leading_zeroes refers to these zeroes.
θ,tanθ = θ_tanθ_from_A_tanA (angleA, tanA)
    '''
    θ, tanθ = angleA, tanA
    for p in range (1,100) :
        θ /= 2
        tanθ = tan_halfA(tanθ)
        if tanθ >= dD('1e-' + str(number_of_leading_zeroes)) : continue
        str1 = str(tanθ)
        # str1 = "n.nnnnnnnnnnnnn ..... nnnnnnnnnnnnE-11"
        str1a = str1[0] + str1[2:-4]
        list1 = [ str1a[q:q+5] for q in range (0, len(str1a), 5) ]
        str2 = '0.00000_00000_' + ('_'.join(list1))
        dD2 = dD(str2)
        (dD2 == tanθ) or ({}[2])
        ((θ * (2**p)) == angleA ) or ({}[3])
        str3 = 'dD({}) / (2 ** ({}))'.format(angleA,p)
        (θ == eval(str3)) or ({}[4])
        return str3, str2
    ({}[5])


r3 = dD(3).sqrt()
r5 = dD(5).sqrt()
tan36 = (5 - 2*r5).sqrt()
tan45 = dD(1)
tan30 = r3/3

v1 = 3*r5+7
v2 = (5 - 2*r5).sqrt()
v3 = (r5+3)*r3
tan24 = ( v1*v2 - v3 )/2

v1 = r5 - 3 ; v2 = (10 - 2*r5).sqrt()
tan27 = ( 11 - 4*r5 + v1*v2 ).sqrt()


values_of_A_tanA = (
    (dD(45), tan45),
    (dD(36), tan36),
    (dD(30), tan30),
    (dD(27), tan27),
    (dD(24), tan24),
)

values_of_θ_tanθ = []
for (A, tanA) in values_of_A_tanA :
    θ, tanθ = θ_tanθ_from_A_tanA (A, tanA)
    print()
    sx = 'θ' ; print (sx, '=', eval(sx))
#    sx = 'tanθ' ; print (sx, '=', eval(sx))
    print ('tanθ =', '{}.....{}'.format(tanθ[:30], tanθ[-20:]))
    values_of_θ_tanθ += [ (θ, tanθ) ]

# Check
for (v1,v2),(v3,v4) in zip (values_of_A_tanA, values_of_θ_tanθ) :
    A, tanA = v1,v2
    θ = eval(v3)
    tanθ = dD(v4)
    status = 0
    for p in range (1,100) :
        θ *= 2
        tanθ = tan_2A (tanθ) 
        if θ == A :
            dgt.prec = desired_precision
            (+tanθ == +tanA) or ({}[10])
            dgt.prec = Precision            
            status = 1
            break
    status or ({}[11])
θ = dD(45) / (2 ** (33))
tanθ = 0.00000_00000_91432_37995_4197.....089_03901_63759_3912

θ = dD(36) / (2 ** (33))
tanθ = 0.00000_00000_73145_90396_3357.....211_97500_56173_0713

θ = dD(30) / (2 ** (33))
tanθ = 0.00000_00000_60954_91996_9464.....024_32806_94580_0689

θ = dD(27) / (2 ** (33))
tanθ = 0.00000_00000_54859_42797_2518.....791_30634_03540_9738

θ = dD(24) / (2 ** (32))
tanθ = 0.00000_00000_97527_87195_1143.....736_60376_04724_6778
# python code

def calculate_π (angleθ, tanθ) :
    '''
angleθ may be: "dD(27) / (2 ** (33))"
tanθ may be: "0.00000_00000_54859_42797_ ..... _03540_9738"
π = calculate_π (angleθ, tanθ)
    '''
    thisName = 'calculate_π (angleθ, tanθ) :'

    if isinstance(angleθ, dD) : pass
    elif isinstance(angleθ, str) : angleθ = eval(angleθ)
    else : ({}[21])
    if isinstance(tanθ, dD) : pass
    elif isinstance(tanθ, str) : tanθ = dD(tanθ)
    else : ({}[22])
    
    x = tanθ ; multiplier = -1 ; sum = x ; count = 0; status = 0

    #         x**3   x**5   x**7   x**9
    # y = x - ---- + ---- - ---- + ----
    #           3      5      7      9
    # 
    # Each term in the sequence is roughly the previous term multiplied by x**2.
    # Each value of x contains 10 leading zeroes after decimal point.
    # Therefore, each term in the sequence is roughly the previous term with 20 more leading zeroes.
    # Each pass through main loop adds about 20 digits to current value of sum
    # and θ is calculated to precision of 1004 digits with about 50 passes through main loop.
    # 
    for p in range (3,200,2) :
        # This is main loop.
        count += 1
        addendum = (multiplier * (x**p)) / p
        sum += addendum
        if abs(addendum) < Tolerance :
            status = 1; break
        multiplier = -multiplier
    status or ({}[23])
    print(thisName, 'count =',count)
    π = sum * 180 / angleθ
    dgt.prec = desired_precision
    π += 0 # This forces π to adopt precision of desired_precision.
    dgt.prec = Precision
    return π

# Calculate five values of π:
values_of_π = []
for θ,tanθ in values_of_θ_tanθ :
    π = calculate_π (θ,tanθ)
    values_of_π += [ π ]

Each calculation of π required about 50 passes through main loop:

calculate_π (angleθ, tanθ) : count = 50
calculate_π (angleθ, tanθ) : count = 49
calculate_π (angleθ, tanθ) : count = 49
calculate_π (angleθ, tanθ) : count = 49
calculate_π (angleθ, tanθ) : count = 50

Check that all 5 values of π are equal:

# python code

set1 = set(values_of_π)
sx = 'len(values_of_π)' ; print (sx, '=', eval(sx))
sx = 'len(set1)' ; print (sx, '=', eval(sx))
sx = 'set1' ; print (sx, '=', eval(sx))
π, = set1 # Note the syntax. If length of set1 is not 1, this statement fails.
len(values_of_π) = 5
len(set1) = 1
set1 = {Decimal('3.141592653589793238462643383279.....12268066130019278766111959092164201989')}

Because all five calculated values of π are equal, there is very high probability that this value of π is accurate.


Print value of π as python command formatted:

# python code

newLine = '''
'''[-1:]

def print_π (π) :
    '''
Input π is : Decimal('3.141592653589793238 ..... 66111959092164201989')
This function prints:
π = ( "3.14159_26535_89793_23846_26433_83279_50288_41971_69399_37510"
     +  "58209_74944_59230_78164_06286_20899_86280_34825_34211_70679"
     .....
     +  "18577_80532_17122_68066_13001_92787_66111_95909_21642_01989" )
    '''
    πstr = str(π)
    (len(πstr) == (desired_precision + 1)) or ({}[31])
    (πstr[:2] == '3.') or ({}[32])

    twenty_rows = []
    for p in range (2, len(πstr), 50) :
        str1a = πstr[p:p+50]
        list1a = [ str1a[q:q+5] for q in range(0, len(str1a), 5) ]
        str1b = '_'.join(list1a)
        twenty_rows += [str1b]
    twenty_rows[0] = '3.' + twenty_rows[0]
    joiner = '"{}     +  "'.format(newLine)
    str3 = '( "{}" )'.format(joiner.join(twenty_rows))
    
    str4 = eval(str3)
    (dD(str4) == π) or ({}[33])

    lines = str3.split(newLine)
    paragraphs = [ newLine.join(lines[p:p+4]) for p in range(0,len(lines),4) ]
    str5 = (newLine*2).join(paragraphs)

    str6 = eval(str5)
    (dD(str6) == π) or ({}[34])
    print ('π =', str5)
    
    return str5

π1 = print_π (π)
π = ( "3.14159_26535_89793_23846_26433_83279_50288_41971_69399_37510"
     +  "58209_74944_59230_78164_06286_20899_86280_34825_34211_70679"
     +  "82148_08651_32823_06647_09384_46095_50582_23172_53594_08128"
     +  "48111_74502_84102_70193_85211_05559_64462_29489_54930_38196"

     +  "44288_10975_66593_34461_28475_64823_37867_83165_27120_19091"
     +  "45648_56692_34603_48610_45432_66482_13393_60726_02491_41273"
     +  "72458_70066_06315_58817_48815_20920_96282_92540_91715_36436"
     +  "78925_90360_01133_05305_48820_46652_13841_46951_94151_16094"

     +  "33057_27036_57595_91953_09218_61173_81932_61179_31051_18548"
     +  "07446_23799_62749_56735_18857_52724_89122_79381_83011_94912"
     +  "98336_73362_44065_66430_86021_39494_63952_24737_19070_21798"
     +  "60943_70277_05392_17176_29317_67523_84674_81846_76694_05132"

     +  "00056_81271_45263_56082_77857_71342_75778_96091_73637_17872"
     +  "14684_40901_22495_34301_46549_58537_10507_92279_68925_89235"
     +  "42019_95611_21290_21960_86403_44181_59813_62977_47713_09960"
     +  "51870_72113_49999_99837_29780_49951_05973_17328_16096_31859"

     +  "50244_59455_34690_83026_42522_30825_33446_85035_26193_11881"
     +  "71010_00313_78387_52886_58753_32083_81420_61717_76691_47303"
     +  "59825_34904_28755_46873_11595_62863_88235_37875_93751_95778"
     +  "18577_80532_17122_68066_13001_92787_66111_95909_21642_01989" )
 
Value of   highlighted.

If you highlight the above expression for   as shown in diagram, you can copy and paste it into your python source file as valid python code.

Discussion questions

edit
  • What are useful applications of pi in engineering or science?
  • How is pi useful in computer science?

See also

edit