1. 程式人生 > >零基礎學演算法->階乘

零基礎學演算法->階乘

開發十年,就只剩下這套架構體系了! >>>   

階乘

在數學中,正整數的階乘(英語:factorial)是所有小於及等於該數的正整數的積,計為n!
例如5的階乘為5!,其值=120; 5!=5x4x3x2x1=120

用遞迴計算階乘

一般數字的階乘可以用遞迴的方法進行計算。

以下用遞迴計算1~12階乘值;階乘的值是以指數進行增長。

Sub Factorial_Main()
Dim num%, m%
Dim FactorNum&
With Sheet9
For num = 1 To 12
    m = 5 + num
    'if num>13 program will overflow
    FactorNum = Factorial_Recursion(num)
    .Cells(m, 1) = num
    .Cells(m, 2) = FactorNum
Next num
End With
Debug.Print Timer
End Sub

'Factorial by Recursion Method
Function Factorial_Recursion(ByVal n)
If n <= 1 Then
    Factorial_Recursion = 1
    Exit Function
Else
    Factorial_Recursion = n * Factorial_Recursion(n - 1)
End If
End Function

大數階乘

一般階乘的值都比較大,這時遞迴的方法不可行。此時需要用陣列儲存階乘結果來進行計算。

思路: 
 1. 當前值乘以陣列中的值
 2. 將結果儲存到陣列中
 3. 判斷每個元素是否需要進位
 4. 使用一個數組來儲存階乘每一位結果

以下是1~100的階乘

具體程式碼如下:

'log10:https://baike.baidu.com/item/%E5%AF%B9%E6%95%B0%E5%87%BD%E6%95%B0/6013318?fr=aladdin

'Calculate the Carry
Function Carry_Bit(ByRef Bit, ByVal Pos)
Dim i&
Dim Carry

Carry = 0                       'Initial
For i = 1 To Pos                'Check 1~Pos whether need carry bit
    Bit(i) = Bit(i) + Carry    'Current value+Carry value
    If Bit(i) <= 9 Then         '<9 no need carray bit
        Carry = 0
    ElseIf Bit(i) > 9 And i < Pos Then   '>9 but <highest digit
        Carry = Int(Bit(i) / 10)         'Save carry
        Bit(i) = Bit(i) Mod 10           'one digit
    ElseIf Bit(i) > 9 And i >= Pos Then  '>9 and highest digit
        Do While Bit(i) > 9
            Carry = Int(Bit(i) / 10)     'Save carry
            Bit(i) = Bit(i) Mod 10       'one digit
            i = i + 1
            Bit(i) = Carry               'Save the carry
        Loop
    End If
Next i
Carry_Bit = Bit                 'Return the Array
End Function


'Calculate multiple number factor
'Loop m
Sub Factorial_BigNumber_Multiple()
Dim num
Dim Digit, sum
Dim i, j
Dim Fact()
Dim Count, Str$
Dim m, n

With Sheet10
For m = 10 To 43
    sum = 0: Digit = 0
    num = .Cells(m, 10).Value       'Input Value
    For i = 1 To num                       'Calculate Result digit
        sum = Log10(i) + sum
    Next i
    Digit = Int(sum) + 1                   'Length of Data
    ReDim Fact(1 To Digit)                 'Allocate Array
    
    For i = 1 To Digit                     'Initial Array
        Fact(i) = 0
    Next i
    Fact(1) = 1                            'Setup 1st digit
    
    For i = 1 To num                       'Loop fact num
        Pos = Highest_Digit(Fact, Digit)   'Record highest digit
        For j = 1 To Pos
            Fact(j) = Fact(j) * i         'fact(n-1)xN
        Next j
        Fact = Carry_Bit(Fact, Pos)   'process carry bit
    Next i
    
    Pos = Highest_Digit(Fact, Digit)   'Record highest digit
'    m = 10
    n = 12                       'Initial
    i = Pos
    Str = "'"
    Count = 0
    Do While i <= Pos And i >= 1
        Count = Count + 1
        Str = Str & Fact(i)
        If Count Mod 5 = 0 Then
            .Cells(m, n) = Str
            Str = "'"
            n = n + 1
        End If
        If i = 1 And Str <> "" Then .Cells(m, n) = Str
        i = i - 1
    Loop
    .Cells(m, 11) = Count
Next m
End With
Debug.Print Timer
End Sub

'Find Hightest digit
Function Highest_Digit(Arr, n)
Dim i
For i = n To 1 Step -1
    If Arr(i) <> 0 Then
        Highest_Digit = i
        Exit Function
    End If
Next i
End Function

'Function for Log10
Function Log10(ByVal x) As Double
Dim nLog10
nLog10 = Log(x) / Log(10)
Log10 = nLog10
End Function