이번엔 진수 변환과 관련된 실용 모듈 하나 제작해 보겠습니다.
프로그래밍 할대 숫자의 축약적 표현을 위해 16진수를 사용할 경우가 있습니다.
그런데 우리 사람은 10진수(0~9)에 익숙하기 때문에 많은 자리수의 16진수를 볼 경우 바로 10진수로
해석하기 힘들죠...물론 굳이 16진수 값을 프로그램이 아닌 사람이 10진수로 알아 봐야 할 필요가 있느냐고..
물으신다면 할말 없구요^^;
여튼 이렇게 알아보기 힘든(?) 16진수로 표현된 수를 사람이 알아보기 쉬운 10진수로 변환하는 모듈을 제작해 보기로 결심(?)하였습니다.
원리는 이렇습니다.
'16진수 -> 10진수' 변환할 때 '수의 전개' 방식을 사용하는데요..
'수의 전개' 란 이렇습니다.
10진수 101라는 수를 전개 해 보면 다음과 같습니다
123 = (1 * 102) + (2 * 101) + (3 * 100) = 100 + 20 + 3
즉 10의 승수를 곱해 나가면 되는 것이지요...
같은 의미로 101이 16진수라면 다음과 같은 수의 전개를 통해 291이라는 10진수 값을 얻을 수 있습니다.
0x123 = (1 * 162) + (2 * 161) + (3 * 160) = 256 + 32 + 3 = 291
진수와 진수 변환과 관련된 내용은 다음의 글을 참조해 주세요
-> n 진수? 진수변환?
-> 2진수 <-> 8진수, 16진수변환
이렇듯 16진수를 10진수로 변환하기 위해 16승의 곱을 통해 얻을 수 있는데,
이 원리를 모듈화 시켜서 자동으로 변환해 주는 유틸리티를 제작해 보기로 합니다.
static string sequenceOfChars = "0123456789ABCDEF";
static double Convert16To10(string str)
{
double resultValue = 0;
int length = 0;
//소수점을 기준으로 소수점 이상,이하 자리 분리
string[] strArray = str.Split('.');
#region 소수점 이상 값에 대한 10진수 계산
length = strArray[0].Length;
for (int i = 0; i < length; i++)
{
//문자열에서 해당 위치 문자 추출
char c = strArray[0][i];
//16진수값의 10진수 대응값 (ex: A = 10)
int indexOfChar = sequenceOfChars.IndexOf(c);
//16의 몇 승? 구하기
int e = length - (i + 1);
//16진수값의 10진수 대응값 * 16(X승) 값 구하기(ex: 10 * 16의 4승)
for(int j = 0 ; j < e ; j++)
{
indexOfChar *= 16;
}
//각 자릿수 합
resultValue += indexOfChar;
}
#endregion
return resultValue;
} |
Convert16To10 메서드는 16진수 표현의 문자열을 입력 받아서 10진수 숫자로 변환해 주는 로직을 구현합니다.
로직에 대한 설명을 주석으로 대신하며 이 모듈을 사용하는 클라이언크 코드와 결과를 보겠습니다.
static void Main(string[] args)
{
string str = "AC00";
double resultValue = Convert16To10(str);
Console.WriteLine(resultValue);
} |

결과를 보면 16진수'AC00' 을 변환하였더니 10진수 44032가 반환 되었습니다.
이걸로 끝이 아닙니다. 해결해야 할 문제가 하나 더 있습니다.
바로 소수 이하 자리입니다.
지금까지는 16진수 값이 소수점이 없는 (양의) 정수만을 이용한 변환 이었습니다.
그러나 16진수도 소수점 이하 자리를 가질 수 있죠.
소수점이 있는 16진수를 10진수로 '수의 전개'를 하면 다음과 같습니다.
0x123.12 = (1 * 162) + (2 * 161) + (3 * 160) + (1 * 16-1) + (2 * 16-2)
= 256 + 32 + 3 + 0.0625 + 0.0078125 = 291.0703125
즉, 소수점 이하 자리는 16의 마이너스 승을 곱해 나가는 방식입니다.
따라서 우리의 모듈에는 이러한 로직도 포함되어야 합니다.
아래는 수정된 코드 입니다.
static string sequenceOfChars = "0123456789ABCDEF";
static double Convert16To10(string str)
{
double resultValue = 0;
int length = 0;
//소수점을 기준으로 소수점 이상,이하 자리 분리
string[] strArray = str.Split('.');
#region 소수점 이상 값에 대한 10진수 계산
length = strArray[0].Length;
for (int i = 0; i < length; i++)
{
//문자열에서 해당 위치 문자 추출
char c = strArray[0][i];
//16진수값의 10진수 대응값 (ex: A = 10)
int indexOfChar = sequenceOfChars.IndexOf(c);
//16의 몇 승? 구하기
int e = length - (i + 1);
//16진수값의 10진수 대응값 * 16(X승) 값 구하기(ex: 10 * 16의 4승)
for(int j = 0 ; j < e ; j++)
{
indexOfChar *= 16;
}
//각 자릿수 합
resultValue += indexOfChar;
}
#endregion
#region 소수점 이하 값에 대한 10진수 계산
//소수점이하 자리가 있을 경우에만 계산
if (strArray.Length > 1)
{
length = strArray[1].Length;
for (int i = 0; i < length; i++)
{
//문자열에서 해당 위치 문자 추출
char c = strArray[1][i];
//16진수값의 10진수 대응값 (ex: A = 10)
double indexOfChar = sequenceOfChars.IndexOf(c);
//16의 마이너스 몇 승? 구하기
int e = i + 1;
//16진수값의 10진수 대응값 * 16(마이너스 X승) 값 구하기(ex: 1 * 1/16의 2승)
for (int j = 0; j < e; j++)
{
indexOfChar *= (double)1 / 16;
}
//각 자릿수 합
resultValue += indexOfChar;
}
}
#endregion
return resultValue;
} |
코드에서는 소수점 이상 수와 소수점 이하 수를 분리하여 계산하며 이 값을 모두 합하고 있습니다.
테스트 결과는 다음과 같습니다.
static void Main(string[] args)
{
string str = "123.12";
double resultValue = Convert16To10(str);
Console.WriteLine(resultValue);
} |

이제 모듈 제작이 완성되었습니다.
이 모듈이 '16진수 -> 10진수 변환' 이지만 이 로직을 그대로 이용하여 2,8 진수도 10진수로 변환하는 코드를
만드는데 어려움이 없을 것입니다.