Excel VBA 응용

Factorial 계산하기

kwangpal 2023. 12. 3. 22:54
반응형

Factorial

Factorial 은 기호로는 ! 로 나타내고

다음과 같은 수식으로 계산한다.

 

$$ n ! = n \times (n-1) \times (n-2) \times ... \times 1 $$

 

Excel에서도 수식 함수로 FACT()를 사용해서

Factorial을 간단하게 계산할 수 있다.

 

 

그런데 FACT() 함수 안에 입력하는 숫자가 커지면

제대로 계산되지 않는다.

 

Excel의 유효숫자가 15자리밖에 되지 않아서

21! 를 계산하면 51,090,942,171,709,400,000 라고 계산되는데

실제 21! 는 51,090,942,171,709,440,000 로 차이가 있다.

더 큰 숫자를 계산하면 더 큰 오차가 나게 된다.

 

그리고 170! 까지는 계산 결과가 나오긴 하는데

171! 부터는 #NUM! 에러가 나온다.

 

윈도우에 포함된 계산기를 이용해도 모든 숫자가 나오지는 않는다.

 

 

 

그렇지만 정확한 계산 결과를 VBA를 이용해서 얻을 수 있다.

 

우선 시트를 다음과 같이 편집한다.

B3 셀은 Factorial 계산을 할 숫자를 입력하는 곳이다.

 

 

E2 셀은 표시 형식을 텍스트로 변경하자.

계산 결과가 한줄로 나올 위치다.

 

 

파란색 버튼의 이름은 Factorial 로 변경하고

다음 코드를 연결해준다.

 

Sub Factorial_Click()

    Dim Arr(10000) As Integer
    Dim x As Integer, y As Integer, z As Integer
    Dim i As Integer, j As Integer, k As Integer
    Dim num As Integer
    
    [E:N] = ""
    
    num = [B3]
    
    Arr(10000) = 1
    
    For x = num To 2 Step -1
        y = 0
        For i = 10000 To 1 Step -1
            z = y + x * Arr(i)
            y = Int(z / 10)
            Arr(i) = z - 10 * y
        Next i
    Next x
        
    For i = 1 To 10000
        If Arr(i) <> 0 Then
            j = i
            Exit For
        End If
    Next i
    
    For i = j To 10000
        k = Int((i - j) / 10)
        Cells(k + 4, i - j + 1 - 10 * k + 4) = Arr(i)
        [E2] = [E2] & Arr(i)
    Next i
    
End Sub

 

실행버튼을 클릭하면 171보다 큰 숫자를 입력해도

정확한 Factorial 계산 결과를 얻을 수 있다.

 

E2 셀에는 한줄에 모든 숫자가 나오고

E~N 컬럼의 4행부터는 한자리씩 10개의 숫자를 하나의 행에 나열했다.

 

 

 

    Dim Arr(10000) As Integer
    Dim x As Integer, y As Integer, z As Integer
    Dim i As Integer, j As Integer, k As Integer
    Dim num As Integer
    
    [E:N] = ""
    
    num = [B3]
    
    Arr(10000) = 1
    
    For x = num To 2 Step -1
        y = 0
        For i = 10000 To 1 Step -1
            z = y + x * Arr(i)
            y = Int(z / 10)
            Arr(i) = z - 10 * y
        Next i
    Next x

 

위 코드는 10000개의 배열을 정의하고

배열의 10000번째 자리에 1을 입력했다.

 

기본 숫자 1에다 다른 숫자를 곱하는 건데

x를 큰 숫자부터 1씩 줄여가면서

Arr(i) 에 곱해서 z를 계산하고

z를 10으로 나눈 몫을 y에 입력하고

z 에서 10 y 를 빼서 Arr(i) 에 입력했다.

결국 Arr(i) 에는 한자리 숫자만 남게 된다.

 

이 과정을 반복하면 Factorial 계산값이

숫자 하나씩 나눠서 배열에 입력된다.

 

    For i = 1 To 10000
        If Arr(i) <> 0 Then
            j = i
            Exit For
        End If
    Next i

 

위 코드는 계산 결과의 첫번째 자리가 0이 아닌 곳을 찾는 것인데

배열이 10000개나 되다보니

Factorial 계산값의 앞부분은 수많은 0으로 채워진다.

예를 들어 10! 를 계산하면

000000 ... 000000003628800 이 나온다.

 

앞부분의 0을 제외하고

10! = 3628800 이 나올 수 있게 하기 위해

0이 아닌 값이 나오는 자리를 인식해서

그 자리가 어디인지 j에 입력했다.

 

    For i = j To 10000
        k = Int((i - j) / 10)
        Cells(k + 4, i - j + 1 - 10 * k + 4) = Arr(i)
        [E2] = [E2] & Arr(i)
    Next i

 

위 코드는 계산결과를 시트에 출력하는 것이다.

0이 아닌 값이 나오는 자리 j 부터 시작해서

10 자리씩 끊어서 하나의 행에 표시하고

E2 셀에는 모든 숫자를 한줄에 표시한다.

 

반응형

'Excel VBA 응용' 카테고리의 다른 글

Palindrome Number  (0) 2023.12.08
Plot Digitizer  (0) 2023.12.02
TSP (Traveling Salesman Problem)  (0) 2023.11.30
Stop Watch  (0) 2023.11.29
소인수분해  (0) 2023.11.29