본문 바로가기
DSA

기수 변환

by KWONE 2024. 7. 16.

정수값을 임의의 기수(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");
}

 

코드 설명

  1. convert_to_base 함수는 숫자를 입력받아 지정된 기수로 변환한다.
  2. result 배열은 변환된 숫자를 저장하기 위한 배열이다.
  3. while 루프에서 숫자를 기수로 나눈 나머지를 result 배열에 저장한다.
  4. 나머지가 10보다 작으면 문자 '0'에서 나머지만큼 더해서 저장한다.
  5. 나머지가 10 이상이면 문자 'A'에서 나머지를 더한 값을 저장한다.
  6. 숫자가 0이 될 때까지 위 과정을 반복한다.
  7. 최종적으로 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