零基础学算法->PI

本文章是介绍几种计算PI的方法

1.概率法计算PI(又称蒙特卡罗法)

1.1 定义,过程

        在半径为1的圆1/4的区域,通过随机函数产生横纵坐标值x,y;当x*x+y*y<=1时,满足条件。

1.2 结果:

         因为是随机产生的值,PI的结果并不会随着样本数的增加而更接进

7736978158fa6a906404fc64cd49237b5b0.jpg

1.3 代码

具体代码如下

'Use Probability to calculate PI
'Another named Monte Carlo method
Sub PI_Rand()
Dim i, j
Dim num, nTime
Dim x, y, sum, PI
Dim Arr, n

Randomize (Timer)    'Random generator
nTime = 200          'number to test
'num = 100000        'Sample of random
'ReDim Arr(1 To num, 1 To 4)
For j = 1 To nTime          'Test time
    sum = 0
    num = nTime * j
    For i = 1 To num      'Loop Range
        x = Rnd
        y = Rnd
        If x * x + y * y <= 1 Then
            n = n + 1
            sum = sum + 1
            PI = 4 * sum / i
        End If
    Next i
    With Sheet11
        .Cells(j + 1, 10) = j
        .Cells(j + 1, 11) = num
        .Cells(j + 1, 12) = PI
    End With
Next j
Debug.Print Time
End Sub

2.割圆法求PI

2.1 定义,过程

5cef98094fcfc83687131889d5cb342a4fa.jpg

f02cb31bd276d19c1780bea43ed2f47d53a.jpg

2.2 结果

定义公式计算     
Sideiaibici=SQRT(1-b*b)di=1-ciai+1=sqrt(b*b+d*d)PI
6110.50.8660254040.13397460.517638093.00000000
1220.517640.25880.9659258260.034074170.2610523843.105828541
2430.261050.13050.9914448610.008555140.1308062583.132628613
4840.130810.06540.9978589230.002141080.0654381663.139350203
9650.065440.03270.9994645870.000535410.0327234633.141031951
19260.032720.01640.9998661380.000133860.0163622793.141452472
38470.016360.00820.9999665343.3466E-050.0081812083.141557608
76880.008180.00410.9999916338.3666E-060.0040906133.141583892
153690.004090.0020.9999979082.0916E-060.0020453073.141590463
3072100.002050.0010.9999994775.2291E-070.0010226543.141592106
6144110.001020.00050.9999998691.3073E-070.0005113273.141592517

2.3 代码

具体代码如下:

'Use Cutting Circle to calculate PI
'https://zh.wikipedia.org/wiki/%E5%89%B2%E5%9C%86%E6%9C%AF_(%E5%88%98%E5%BE%BD)
'http://blog.sina.com.cn/s/blog_a6f9a3b60101ecp1.html

'Logic please refer the Chart in Worksheet
Sub PI_CutCircle_Formula_2()
Dim i%, num%, side%
Dim Ai#, Bi#, Ci#, Di#
Dim Aj#
Dim PI#
Dim m

With Sheet12
    num = 10           'Large of cutting
    i = 0              'time of cut
    side = 6           'side of Polygon
    Ai = 1
    Do While i <= num   'Loop cutting range
        Bi = Ai / 2
        Ci = Sqr(1 - Bi * Bi)
        Di = 1 - Ci
        PI = side * Ai / 2 * 1 'PI=circumference/diameter
        
        Aj = Sqr(Bi * Bi + Di * Di)   'Next Ai
        m = 24 + i             'row in worksheet
        .Cells(m, 6) = side
        .Cells(m, 7) = i
        .Cells(m, 8) = Ai
        .Cells(m, 9) = Bi
        .Cells(m, 10) = Ci
        .Cells(m, 11) = Di
        .Cells(m, 12) = Aj
        .Cells(m, 13) = PI
                
        i = i + 1               'Next Cut
        Ai = Aj
        side = side * 2
        
    Loop
End With
Debug.Print Timer
End Sub

3.公式法求PI

3.1 定义,过程

88b79b58bafe71c202d9303cec181a37da5.jpg

3.2 结果

随着分子分母不断增加,其值不断接近PI

cdb83132cad70367727fcbbc48e07e0457f.jpg

3.3 代码

具码如下


'Use Formula to calculate PI
'Refer Worksheet 6.4.3
'PI=2+2/3+2/3*2/5+2/3*2/5*3/7.....
'numerator+1, denominator+2
Sub PI_Formula_Calc()
Dim PI#, temp#
Dim numerator%, denominator%
Dim m, Str$

m = 6
PI = 2          'Initial
temp = 2
numerator = 1
denominator = 3

With Sheet14
    Do While temp > 1E-16         '=0.0000000000000016
        temp = temp * numerator / denominator
        Str = "'" & CStr(numerator) & "/" & CStr(denominator)
        PI = PI + temp
        .Cells(m, 1) = PI
        .Cells(m, 2) = numerator
        .Cells(m, 3) = denominator
        .Cells(m, 4) = Str
        
        m = m + 1
        numerator = numerator + 1
        denominator = denominator + 2
    Loop
End With
Debug.Print Timer
End Sub

4.计算任意位数的PI

4.1定义,过程

计算PI的过方法和公式法相同,不过需要将计算的结果保存到数组中,并且通过数组的计算将结果输出

4.2 结果

以下结果是1000位的PI,

596757b40278dccf7f9d96787f73b22adc8.jpg

4.3 代码

具体代码如下

'Calculate the PI Long Digital Number
'2+tmp*numerator/denominator

Sub Long_Digital_PI()
Dim t
Dim lenPI, i
Dim flag, count
Dim PI(), tmp()
Dim carry
Dim numerator, denominator, result
Dim Str$
Dim m%, n%

t = Timer
lenPI = 1000                 'Initial lenth of PI
'Leave PI(0) AND PI(tie) for calculation use
ReDim PI(0 To lenPI)     'Allocate Array
ReDim tmp(0 To lenPI)    'Allocate Array

'Initial Number
PI(1) = 2
tmp(1) = 2
flag = 1
numerator = 1
denominator = 3
Str = ""
m = 10
'n = 0

Do While flag And count < 214748364     'Largest Int
    carry = 0
    For i = lenPI To 1 Step -1          'multipy numerator from Lower->High
        result = tmp(i) * numerator + carry  'Each digit + carry in
        tmp(i) = result Mod 10          'Reminder
        carry = Int(result / 10)            'Carry in
        count = count + 1
    Next i
    
    carry = 0
    For i = 1 To lenPI Step 1            'divide denominator from High->Lower
        result = tmp(i) + carry * 10     'reminder from previous
        tmp(i) = Int(result / denominator)  'intege of current number
        carry = result Mod denominator   'reminder of current number, goto next lower
        count = count + 1
    Next i
    
    flag = 0
    For i = lenPI To 1 Step -1     'Cumulate result
        result = PI(i) + tmp(i)
        PI(i) = result Mod 10          '1 digit in array
        PI(i - 1) = PI(i - 1) + Int(result / 10) 'carry to high digit
        flag = flag + PI(i)           'if all PI()=0 then exit sub
        count = count + 1
    Next i
    
    numerator = numerator + 1
    denominator = denominator + 2
    If flag > 0 Then flag = 1
Loop

With Sheet13               'Output Result
    n = 1
    Str = PI(1) & "."      'Integer Parts
    For i = 2 To lenPI
        Str = Str & PI(i)
        If i > 2 And (i - 2) Mod 10 = 0 Then
            If (i - 2) Mod 50 = 0 Then
                .Cells(m, n) = Str
                m = m + 1
                n = 1
            Else
                .Cells(m, n) = Str
                n = n + 1
            End If
            .Cells(m, n) = Str
            Str = ""
        End If
    Next i
    
End With
Debug.Print Timer - t
End Sub

 

转载于:https://my.oschina.net/tedzheng/blog/3042775

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值