로마 숫자란 무엇인가?
로마 숫자는 자릿값(위치)에 따라 값이 달라지지 않는 비위치적(non-positional) 기수법입니다. 여러 개의 기호를 나란히 조합하여 하나의 수를 표현하며, 각 기호의 값을 모두 더해 전체 숫자를 나타냅니다.
예를 들어 75라는 숫자는 50 + 10 + 10 + 5로 분해할 수 있으며, 이를 로마 숫자로 표현하면 LXXV가 됩니다.
이 글에서는 10진수 형태로 주어진 숫자를 로마 숫자 문자열로 변환하는 방법과, 이를 구현한 알고리즘 및 C++ 코드를 살펴보겠습니다.
로마 숫자 기호와 값
로마 숫자에서 사용되는 기호와 그 값은 다음과 같습니다.
| 기호 | 값 |
|---|---|
| I | 1 |
| IV | 4 |
| V | 5 |
| IX | 9 |
| X | 10 |
| XL | 40 |
| L | 50 |
| XC | 90 |
| C | 100 |
| CD | 400 |
| D | 500 |
| CM | 900 |
| M | 1000 |
| MMMM | 4000 |
| V' | 5000 |
이 표를 활용하면 주어진 숫자에 해당하는 로마 숫자를 쉽게 찾을 수 있습니다. 핵심은 숫자에서 뺄 수 있는 가장 큰 기호 값을 찾아 차감하고, 남은 값에 대해 같은 과정을 반복하는 것입니다.
입력 및 출력 예시
Input:
Decimal number: 3569
Output:
The Roman equivalent of 3569 is: MMMDLXIX
알고리즘
변환 함수는 다음과 같이 정의됩니다.
decToRoman(nuList, num)
입력: 기호와 값이 담긴 목록(nuList), 로마 숫자로 변환할 수(num)
출력: 주어진 숫자에 해당하는 로마 숫자
동작 과정은 다음과 같습니다.
Begin
if num ≠ 0, then
max := num보다 크지 않은 최대 기호 값을 찾음
display the nuList[max].symbol
num := num – nuList[max].value
decToRoman(nuList, num) // 남은 값에 대해 재귀 호출
End
이 알고리즘은 매 단계에서 처리 가능한 가장 큰 값을 선택하는 그리디(greedy) 방식으로 동작하며, 남은 숫자가 0이 될 때까지 재귀적으로 반복합니다.
C++ 구현 예제
#include<iostream>
using namespace std;
struct numeral {
string sym;
int val;
};
int maxNume(numeral nu[], int num) {
int index;
for(int i = 0; i<15; i++) // 배열에는 15개의 기호가 있음
if(nu[i].val<= num)
index = i;
// num보다 크지 않은 가장 큰 값의 인덱스 반환
return index;
}
void decToRoman(numeral nu[], int num) {
int max;
if(num != 0) {
max = maxNume(nu, num);
cout << nu[max].sym;
num -= nu[max].val; // 숫자 감소
decToRoman(nu, num); // 재귀적으로 기호 출력
}
}
int main() {
int number;
numeral nume[15] = {{"I",1},{"IV",4},{"V",5},{"IX",9},
{"X",10},{"XL",40},{"L",50},{"XC",90},
{"C",100},{"CD",400},{"D",500},{"CM",900},
{"M",1000},{"MMMM",4000},{"V'",5000}
};
cout << "Enter a decimal number: "; cin >> number;
if(number >0 && number <= 5000) { // 입력 범위 검사
cout<<"The Roman equivalent of " << number<<" is: ";
decToRoman(nume, number);
}else {
cout << "Invalid Input";
}
}
실행 결과
Enter a decimal number: 3569
The Roman equivalent of 3569 is: MMMDLXIX
정리
10진수를 로마 숫자로 변환하는 문제는 기호와 값의 대응표를 준비한 뒤, 큰 값부터 차감해 나가는 그리디 알고리즘으로 해결할 수 있습니다. 위 코드처럼 재귀 함수를 사용하면 로직이 간결해지며, 입력 범위 검사를 추가하면 잘못된 입력도 안전하게 처리할 수 있습니다.