정수값을 임의의 기수(cardinal number)로 변환하는 알고리즘
10진수 정수를 n진수 정수로 변환하려면 정수를 n으로 나눈 나머지를 구하는 동시에 그 몫에 대해 나눗셈을 반복해야 함
이 과정을 몫이 0이 될 때까지 반복하고, 이런 과정으로 구한 나머지를 거꾸로 늘어 놓은 숫자가 기수로 변환한 숫자이다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
/*---type형 x값과 y값을 교환하는 매크로---*/
#define swap(type,x,y) do{type t=x;x=y;y=t;}while(0)
/*---정수값 x를 n진수로 변환한 숫자 문자의 정렬을 배열 d에 저장---*/
int card_conv(unsigned x, int n, char d[])
{
char dchar[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int digits = 0; //변환 후 자릿수
if (x == 0) //0이면
d[digits++] = dchar[0]; //변환 후에도 0
else
while (x) {
d[digits++]= dchar[x % n]; //n으로 나눈 나머지를 저장
x /= n;
}
for (int i = 0; i < digits / 2; i++)
swap(char, d[i], d[digits - i - 1]);
return digits;
}
int main()
{
puts("10진수를 기수 변환합니다.");
int retry;
do {
unsigned no; //변환하려는 정수
int cd; //기수 (몇 진수로 변환할지 확인)
char cno[512]; //변환한 값의 각 자리 숫자를 저장하는 문자 배열
printf("변환하는 음이 아닌 정수: ");
scanf("%d", &no);
do {
printf("어떤 진수로 변환할까요?(2-36) ");
scanf("%d", &cd);
} while (cd < 2 || cd>36);
int dno = card_conv(no, cd, cno); //no를 dno자리의 cd진수로 변환
printf("%d진수로는", cd);
for (int i = 0; i < dno; i++)
printf("%c", cno[i]);
printf("입니다.\n");
printf("한 번 더 할까요?(1...예/0...아니오): ");
scanf("%d", &retry);
} while (retry == 1);
return 0;
}
알고리즘
1. 10진수 숫자를 목표 진법의 기수로 나누고, 나머지를 저장한다.
2. 숫자가 0이 될때 까지 반복한다.
3. 나머지를 역순으로 정렬한다. 혹은 출력한다.
코드 설명
char dchar[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
위 배열을 선언함에 따라 dchar[0]=0이되고
순차적으로 dchar[9]=9, dchar[10]=A, dchar[11]=B... 처럼 숫자들이 인덱스 넘버와 같은 값을 의미하므로
값을 인덱스 넘버로 생각하고 사용할 수 있게 되었다.
if (x == 0) //0이면
d[digits++] = dchar[0]; //변환 후에도 0
else
while (x) {
d[digits++]= dchar[x % n]; //n으로 나눈 나머지를 저장
x /= n;
}
card_conv() 함수는 x를 n진수로 변경하여 배열d[]에 저장하는 함수이다.
따라서 x가 0인 경우에는 그대로 0이 되지만 그게 아닌 경우에는 (else)
먼저 x를 n으로 나눈 나머지를 인덱스로 하는, 배열 dchar[] 안의 문자 dchar[x%n]을 배열 d의 요소 d[digits]에 일단 저장후
digits값을 하나 증가하여 다음 수행을 준비한다. 그후 x를 n으로 나누어서 x가 0이될때 까지 전체적인 과정을 반복한다.
예를 들어 x%n이 11이면 (dchar[11]은 'B'이다.) 문자 'B'를 d[digits]에 저장하고 digits를 하나 증가한다.
digits=0으로 초기화 되어있으니 d[0]부터 하나씩 dchar[x%n]값이 저장되고 d[1]로 넘어가는 식이다.
59를 16진수로 변환할때, d[0]에 dchar[59%16]인 dchar[11], 즉 B가 우선 저장되고 다음으로 d[1]에 dchar[3]이 저장된다.
이후 x는 0이므로 반복을 종료하고 digits은 2가됨을 확인할 수있다. digits는 자릿수를 의미한다.
나머지를 구하는 순서대로 배열 d에 저장되므로 d[0]=B, d[1]=3, 올바른 16진법 변환으로는 B3이 아닌 3B가 와야하므로
배열 d[]의 역순 정렬이 필요하다.
for (int i = 0; i < digits / 2; i++)
swap(char, d[i], d[digits - i - 1]);
위 블럭은 배열 d[]의 d[0]~d[digits-1]부분을 역순으로 정렬한다
다른 방식
#include <stdio.h>
// 함수 선언
void convert_to_base(int number, int base);
int main() {
int number, base;
// 사용자로부터 숫자와 기수를 입력받음
printf("변환할 10진수 숫자를 입력하세요: ");
scanf("%d", &number);
printf("변환할 기수를 입력하세요 (예: 2, 8, 16): ");
scanf("%d", &base);
// 기수 변환 함수 호출
convert_to_base(number, base);
return 0;
}
void convert_to_base(int number, int base) {
char result[32]; // 결과를 저장할 배열 (최대 32자리 숫자 처리 가능)
int index = 0;
// 숫자가 0이 될 때까지 반복
while (number > 0) {
int remainder = number % base; // 나머지 계산
if (remainder < 10) {
result[index] = '0' + remainder; // 숫자를 문자로 변환하여 저장
} else {
result[index] = 'A' + (remainder - 10); // 10 이상일 경우 알파벳으로 변환하여 저장 (예: 10 -> A)
}
number /= base; // 숫자를 기수로 나눈 몫으로 갱신
index++;
}
// 배열에 저장된 결과를 역순으로 출력
printf("변환 결과: ");
for (int i = index - 1; i >= 0; i--) {
printf("%c", result[i]);
}
printf("\n");
}
코드 설명
- convert_to_base 함수는 숫자를 입력받아 지정된 기수로 변환한다.
- result 배열은 변환된 숫자를 저장하기 위한 배열이다.
- while 루프에서 숫자를 기수로 나눈 나머지를 result 배열에 저장한다.
- 나머지가 10보다 작으면 문자 '0'에서 나머지만큼 더해서 저장한다.
- 나머지가 10 이상이면 문자 'A'에서 나머지를 더한 값을 저장한다.
- 숫자가 0이 될 때까지 위 과정을 반복한다.
- 최종적으로 result 배열에 저장된 값을 역순으로 출력한다.
'DSA' 카테고리의 다른 글
동적 배열 스택 (0) | 2024.07.22 |
---|---|
스택 (stack) (0) | 2024.07.22 |
연결 리스트 예제 (0) | 2024.07.14 |
연결 리스트 (linked list) (0) | 2024.07.13 |
최대값,최소값,중앙값 찾기 알고리즘 (1) | 2024.06.25 |