Palindrome Number
대칭수 또는 회문수
앞으로 읽어도, 뒤로 읽어도 똑같은 숫자.
예를 들어 11, 121, 1331, 12321 같은 숫자들이다.
한자리 숫자도 모두 대칭수라고 할 수 있겠고.
11보다 크면서
10진수로도 대칭수
8진수로도 대칭수
2진수로도 대칭수인
10 이상의 가장 작은 자연수를
VBA로 구해보자.
우선 시트를 다음과 같이 편집해두고
"대칭수 계산" 이라고 적힌 버튼의 이름을 Palindrome 이라고 정했다.
그리고 다음 코드 중 Sub Palindrome_Click() 을
버튼에 연결해준다.
Function Dec2Bin(ByVal num As Long) As String
Dim result As String
Dim remainder As Long
Do While num > 0
remainder = num Mod 2
'num = num \ 2
num = Int(num / 2)
'result = CStr(remainder) & result
result = remainder & result
Loop
Dec2Bin = result
End Function
Sub Palindrome_Click()
Dim num As Long
Dim num_8 As String
Dim num_2 As String
num = 11
Do While True
num_8 = Oct(num)
num_2 = Dec2Bin(num)
If num = StrReverse(num) And _
num_8 = StrReverse(num_8) And _
num_2 = StrReverse(num_2) Then
[C2] = num
[C3] = num_8
[C4] = num_2
Exit Do
End If
num = num + 2
Loop
End Sub
위 코드를 실행하면 다음과 같은 결과를 얻을 수 있다.
585는 10진수로도 대칭수이고
8진수로도, 2진수로도 대칭수이다.
Function Dec2Bin(ByVal num As Long) As String
Dim result As String
Dim remainder As Long
Do While num > 0
remainder = num Mod 2
num = num \ 2
'num = Int(num / 2)
result = remainder & result
Loop
Dec2Bin = result
End Function
위 코드는 10진수를 2진수로 변환하는 함수를 정의한 것이다.
Excel 수식 함수에도 DEC2BIN() 함수가 있어서
VBA에서 이용할 수도 있긴 하다.
num_2 = WorksheetFunction.Dec2Bin(num)
그런데 왜 변환하는 함수를 따로 정의해서 썼을까?
그 이유는...
DEC2BIN() 함수가 좀 문제가 있는데
511보다 큰 숫자는 변환을 못한다.
그래서 보다 큰 숫자도 변환할 수 있도록
VBA 내에서 함수를 따로 정의한 것이다.
10진수를 8진수로 변환하는 경우
536870911까지 변환이 가능하다.
이정도면 계산을 하기에는 충분히 큰 숫자다.
Do While num > 0
remainder = num Mod 2
num = num \ 2
'num = Int(num / 2)
result = remainder & result
Loop
Dec2Bin = result
숫자(num)를 2로 나눈 나머지(mod)를 remainder 변수에 입력하고
몫을 다시 num에 저장한다.
num = num \ 2 는 num을 2로 나눈 몫을 계산하는 것이다.
num = Int(num / 2) 으로 써도 된다.
그리고 result 변수에는 위에서 계산한 remainder를
이전 result의 앞에 붙인다.
이 계산을 num이 0보다 클 동안 반복하면
10진수가 2진수로 바뀌는 거다.
Sub Palindrome_Click()
Dim num As Long
Dim num_8 As String
Dim num_2 As String
num = 11
Do While True
num_8 = Oct(num)
num_2 = Dec2Bin(num)
If num = StrReverse(num) And _
num_8 = StrReverse(num_8) And _
num_2 = StrReverse(num_2) Then
[C2] = num
[C3] = num_8
[C4] = num_2
Exit Do
End If
num = num + 2
Loop
End Sub
위 코드는 10진수를 8진수와 2진수로 변환하고
각각의 숫자를 거꾸로 해서 원래 숫자와 같은지 확인하고
10진수, 8진수, 2진수 모두 대칭수가 될 때까지 반복하는 것이다.
VBA에서 10진수를 8진수로 바꾸는 것은 Oct() 를 쓰면 된다.
StrReverse() 는 문자열의 순서를 거꾸로 바꾸는 거다.
num 을 11부터 시작한 이유는
10 이상의 가장 작은 자연수라는 조건에서
10은 이미 대칭수가 아니기 때문이고
2진수는 마지막 숫자가 0일 경우
거꾸로 하면 첫 숫자가 0이 되니까
마지막 숫자는 1이어야 하고
그렇다면 10진수는 홀수여야 한다.
코드의 마지막에 num = num + 2 라고 한 이유는
11부터 시작했고, 대칭수의 후보가 홀수여야 하니까
굳이 1씩 더해서 쓸데없는 짝수인 경우를 만들지 않고
2씩 더해서 홀수를 만든 것이다.
이 문제는 "코딩의 수학적 기초를 다지는 알고리즘 퍼즐 68" 이라는 책에 나오는데
책에서는 Python과 JavaScript 코드만 다루기 때문에
VBA로 바꿨다.
'Excel VBA 응용' 카테고리의 다른 글
Factorial 계산하기 (0) | 2023.12.03 |
---|---|
Plot Digitizer (0) | 2023.12.02 |
TSP (Traveling Salesman Problem) (0) | 2023.11.30 |
Stop Watch (0) | 2023.11.29 |
소인수분해 (0) | 2023.11.29 |