일반적으로 10진수를 16진수(밑이 16)로 변환할 때는 0123456789ABCDEF라는 표준 문자 집합을 사용해 각 자릿수를 매핑합니다.
이번에 작성할 함수는 정확히 같은 변환을 수행하되, 사용자가 이 표준 집합 대신 원하는 어떤 문자 집합(스케일)이든 자유롭게 지정할 수 있도록 하는 것이 목표입니다.
예를 들어 다음과 같습니다.
10진수 363의 16진수 표기는 16B입니다. 하지만 사용자가 '0123456789ABCDEF' 대신 'qwertyuiopasdfgh'라는 스케일을 사용하기로 하면, 숫자 363은 wus로 표현됩니다.
그럼 재귀(recursion)를 활용해 정수를 16진수 문자열로 변환하는 toHex() 함수를 만들어 보겠습니다. 이 함수는 총 네 개의 인수를 받지만, 최종 사용자가 직접 다루는 것은 처음 두 개입니다.
- num: 16진수로 변환할 숫자
- hexString: 사용자 지정 스케일(선택 사항). 기본값은 '0123456789ABCDEF'이며, 값을 전달할 경우 반드시 정확히 16자여야 합니다. 그렇지 않으면 함수는 false를 반환합니다.
- hex: 재귀 호출 과정에서 결과를 누적하는 문자열(기본값: 빈 문자열)
- isNegative: 입력값이 음수인지 나타내는 불리언 값
구현 예제
const num = 363;
const toHex = (
num,
hexString = '0123456789ABCDEF',
hex = '',
isNegative = num < 0
) => {
if(hexString.length !== 16){
return false;
}
num = Math.abs(num);
if(num && typeof num === 'number'){
// 재귀적으로 나머지에 해당하는 문자를 앞에 붙이고 num을 16으로 나눕니다
return toHex(Math.floor(num / 16), hexString,
`${hexString[num%16]}${hex}`, isNegative);
};
return isNegative ? `-${hex}` : hex;
};
console.log(toHex(num, 'QWERTYUIOPASDFGH'));
console.log(toHex(num));
console.log(toHex(num, 'QAZWSX0123456789'))
출력 결과
콘솔 출력은 다음과 같습니다.
WUS 16B A05
동작 원리
함수는 먼저 스케일 문자열의 길이가 정확히 16자인지 검증한 뒤, 입력값의 절댓값을 구합니다. 이후 num % 16으로 현재 자릿수에 해당하는 스케일 문자를 찾아 누적 문자열 hex의 앞에 붙이고, Math.floor(num / 16)으로 구한 몫을 가지고 다시 자기 자신을 호출합니다.
num이 0이 되면 재귀가 종료되며, 입력값이 음수였다면 결과 앞에 마이너스(-) 기호를 붙여 최종 문자열을 반환합니다. 이러한 방식 덕분에 표준 16진수 표기뿐 아니라 키보드 배열처럼 완전히 다른 16자 문자열로도 손쉽게 숫자를 표현할 수 있습니다.