이 글에서는 양의 정수(10진수)를 입력받아 해당하는 로마 숫자 표기법으로 변환하여 반환하는 JavaScript 함수를 작성해 보겠습니다.
로마 숫자는 기본 기호 I, V, X, L, C, D, M을 조합하여 숫자를 표현합니다. 4, 9, 40, 90, 400, 900처럼 작은 수가 큰 수 앞에 오는 경우는 뺄셈 표기법을 사용하므로, 이러한 규칙을 미리 매핑 테이블로 정의해 두면 변환 로직을 간단하게 만들 수 있습니다.
1. 로마 숫자 매핑 테이블 정의
먼저 자릿수별 값과 그에 대응하는 로마 숫자를 객체 형태로 정의합니다. 이 테이블은 1부터 9000까지의 주요 자릿수 값을 모두 포함하고 있습니다.
const legend = {
1: 'I', 2: 'II', 3: 'III', 4: 'IV', 5: 'V',
6: 'VI', 7: 'VII', 8: 'VIII', 9: 'IX',
10: 'X', 20: 'XX', 30: 'XXX', 40: 'XL', 50: 'L',
60: 'LX', 70: 'LXX', 80: 'LXXX', 90: 'XC',
100: 'C', 200: 'CC', 300: 'CCC', 400: 'CD', 500: 'D',
600: 'DC', 700: 'DCC', 800: 'DCCC', 900: 'CM',
1000: 'M', 2000: 'MM', 3000: 'MMM', 4000: 'MMMM',
5000: 'MMMMM', 6000: 'MMMMMM', 7000: 'MMMMMMM',
8000: 'MMMMMMMM', 9000: 'MMMMMMMMM'
};2. 변환 함수 구현
변환 알고리즘의 핵심 아이디어는 다음과 같습니다.
① 숫자를 문자열로 변환한 뒤 한 글자씩 분리하고 역순으로 배열에 저장합니다.
② 각 자릿수에 자리값(1, 10, 100, 1000...)을 곱해 실제 값을 계산합니다.
③ 매핑 테이블에서 해당 값의 로마 숫자를 찾아 연결합니다.
④ 마지막으로 다시 역순으로 배치하여 원래 순서대로 합치면 완성됩니다.
실제 코드는 다음과 같습니다.
const decimalToRoman = (num = 1) => {
const legend = {
1: 'I', 2: 'II', 3: 'III', 4: 'IV', 5: 'V',
6: 'VI', 7: 'VII', 8: 'VIII', 9: 'IX',
10: 'X', 20: 'XX', 30: 'XXX', 40: 'XL', 50: 'L',
60: 'LX', 70: 'LXX', 80: 'LXXX', 90: 'XC',
100: 'C', 200: 'CC', 300: 'CCC', 400: 'CD', 500: 'D',
600: 'DC', 700: 'DCC', 800: 'DCCC', 900: 'CM',
1000: 'M', 2000: 'MM', 3000: 'MMM', 4000: 'MMMM',
5000: 'MMMMM', 6000: 'MMMMMM', 7000: 'MMMMMMM',
8000: 'MMMMMMMM', 9000: 'MMMMMMMMM'
};
// 숫자를 문자열로 바꿔 한 글자씩 분리한 후 역순 정렬
const arr = num.toString().split('').reverse();
let i = 1, k;
// 각 자릿수에 자리값(1, 10, 100, ...) 곱하기
for (k = 0; k < arr.length; k++) {
arr.splice(k, 1, arr[k] * i);
i *= 10;
}
// 매핑 테이블에서 로마 숫자 조회
const romansArray = [];
for (i = 0; i < arr.length; i++) {
romansArray.push(legend[arr[i]] || '');
}
// 원래 순서대로 복원 후 문자열로 결합
return romansArray.reverse().join('');
};
console.log(decimalToRoman(345));3. 실행 결과 확인
예제 코드를 실행하면 콘솔에 다음과 같은 결과가 출력됩니다.
CCCXLV
345는 백의 자리 300(CCC), 십의 자리 40(XL), 일의 자리 5(V)로 분해되어 CCCXLV로 변환됩니다. 여기서 40이 XL로 표현된 것은 로마 숫자의 뺄셈 표기법(작은 기호가 큰 기호 앞에 오면 두 값의 차를 의미) 때문입니다.
4. 마무리
이처럼 자릿수별 매핑 테이블을 활용하면 복잡한 조건문 없이도 깔끔하게 10진수를 로마 숫자로 변환할 수 있습니다. 다만 전통적으로 로마 숫자는 3999까지만 표기하는 것이 일반적이므로, 실무에서는 입력값 범위 검증을 추가하는 것이 좋습니다.