본문으로 바로가기
반응형

 

1. 개요

 

수학 교육 과정에서 배운 진법 변환을 코드로 구현해보자. 10진법에서 N진법으로, N진법에서 10진법으로 변환하는 방법을 알아본다.

수학에서 변환했던 방법을 생각하며 아래의 진법 변환을 알아보자.

 

 

2. 10진법에서 N진법으로 변환하기

 

10진법에서 N진법으로의 변환은 매우 쉽다. 수학으로 생각하면 10진법으로 표기된 숫자를 N으로 나누어 그 나머지를 표시하고 더 이상 나눌 수 없을 때까지 반복하여 표기하는 방식이다.

예를 들어 10진법 5를 3진법으로 바꾼다면, 5를 3으로 나누면 나머지 2에 몫은 1이다. 최종 나누어진 값부터 표시하므로 12가 된다.

 

이를 자바 코드로 살펴보자.

public class Conversion {
    public static void main(String[] args) {
        int number = 127; // 진법 변환할 숫자
		
        conversion(number,  2); // 2진법 변환
        conversion(number,  3); // 3진법 변환
        conversion(number,  4); // 4진법 변환
        conversion(number,  5); // 5진법 변환
        conversion(number,  8); // 8진법 변환
        conversion(number,  16); // 16진법 변환
        
        // 이외 자바 내에서 제공하는 방식을 사용 시,
        System.out.println(Integer.toBinaryString(number)); // 2진법 변환
        System.out.println(Integer.toOctalString(number));  // 8진법 변환
        System.out.println(Integer.toHexString(number));    // 16진법 변환
    }
	
    public static void conversion(int number, int N){
        StringBuilder sb = new StringBuilder();
	    int current = number;
	    
        // 진법 변환할 숫자가 0보다 큰 경우 지속 진행
        while(current > 0){
            // 만약 N으로 나누었는데 10보다 작다면 해당 숫자를 바로 append
            if(current % N < 10){
                sb.append(current % N);
                
            // 만약 N이 10보다 큰 경우, N으로 나누었는데 10 이상이면 A, B등으로 표현하므로 기존 숫자는 10진법이므로 10만큼 빼고 'A'를 더한다. 
            // 왜냐면 1~9까지는 숫자로 표기하지만, 10 부터는 'A', 'B' 순서로 나타내기 때문이다.
            // 나머지가 10이라면 'A' + 10이 아니라 'A'로 나타내야 하기 때문
            } else {
                sb.append((char)(current % N - 10 + 'A'));
            }
            current /= N;
        }
        // StringBuilder의 reverse를 사용해야 정상적으로 출력 가능. 안그러면 거꾸로 출력됨
        System.out.println("숫자 : " + number + "를 " + N + "진법으로 변환한 수 : " + sb.reverse());
    }
}

 

 

3. N진법에서 10진법으로 변환하기

 

그럼 반대로, N진법에서 10진법으로 변환하는 방법은 어떻게 될까?

이 또한 간단하게 수학적으로 이용하여 N진법의 각 숫자에 N을 곱해가면서 10진법으로 다시 바꾸면 된다. 아래의 코드를 통해 알아보자.

 

아래의 코드에서 자바로 쉽게 진행할 수 있는 방법도 알아본다.

public class Main {
    public static void main(String[] args) {
	    
        // String 형태로 해서 전달함. 7F등 10진법 이상에서는 A~Z의 문자를 사용하기 때문
        // 전체 숫자를 다시 원래 숫자 127로 변환!
        converse_ten("1111111", 2);
        converse_ten("11201", 3);
        converse_ten("1333", 4);
        converse_ten("1002", 5);
        converse_ten("177", 8);
        converse_ten("7F", 16);
        
        // 쉽게 진행하는 법 - 자바 내부에서 제공하는 방법 사용
        // Integer.parseInt 진행 시, 숫자와 진법을 제공하면 10진법으로 쓰여진다.
        System.out.println(Integer.parseInt("7F", 16));
    }
	
    public static void converse_ten(String number, int N){
        char[] nums = number.toCharArray(); // char의 배열로 만들어서 하나씩 숫자별로 대응
        int ans = 0; // 시작은 0으로 시작
        
        // 아래에서 ans를 0으로 시작하고 계속 N(기존 진법)을 곱하고 있다.
        // 이는, 앞자리의 숫자는 전체 m자리라면 m-1승 까지 곱해야 하기 때문
        // 1의 자리는 0승 곱하면 되기 때문에 0으로 시작하는 것임
        for(int i=0; i < nums.length; i++){
            // 'A'이상의 숫자, 즉 10이상의 경우에는 'A'를 빼고 10을 더하면 원래 숫자가 됨
            if(nums[i] >= 'A'){
                ans = ans * N + (nums[i] - 'A' + 10);
            // 그 이하는 단순히 '0'만 빼면 된다.     
            } else {
                ans = ans * N + (nums[i] - '0');
            }
        }
        System.out.println(ans);
    }
}

 

 

위의 코드를 이용해서 A - B 진법으로의 변환도 가능하다. 10진법을 중간에 끼워서 상호 변환 시키는 과정이나, 위의 코드를 기반으로 쉽게 해결할 수 있다.

 

 

4. 2진법 - 16진법 변환하기

 

위에서 A - B 진법으로 변환은 10진법을 중간에 끼워서 코드를 동작시키면 된다고 했는데,
여기서는 2진법과 16진법을 상호 변환하는 방법을 알아보자.

 

2진법 - 16진법은 실제로 많이 쓰이는 경우가 많으므로 여기서 포스팅을 수행하였다.

 

2진법 → 16진법

2진법의 숫자 4개를 이용 시, 0~15까지의 숫자를 나타낼 수 있다.

그렇다면, 16진법은 0~15까지를 하나의 숫자 혹은 문자로 나타내는 방법이므로 2진법의 숫자 4개씩 잘라서 변환을 시키면 된다. 아래의 표를 보자.(아래와 같이 변환 가능)

2진법 16진법
0000 0
0001 1
0010 2
0011 3
0100 4
0101 5
0110 6
0111 7
1000 8
1001 9
1010 10(A)
1011 11(B)
1100 12(C)
1101 13(D)
1110 14(E)
1111 15(F)

 

그렇다면, 1000 1100 은 16진법으로 어떻게 변환될까? 바로 8C 임을 알 수 있다.

주의할 점은, 2진법의 숫자가 10 1100 이면 4개로 정확히 끊어지지 않는다는 점이다. 이럴 때는, 앞에 00을 붙여 4개로 끊어지도록 만듦으로써 문제를 쉽게 해결할 수 있다.

코드를 통해 어떻게 변환이 되는지 알아보자.

public class Main {
    public static void main(String[] args) {
        System.out.println(bin2Hex("1101"));   // 0xD
        System.out.println(bin2Hex("100110")); // 0x26
        System.out.println(bin2Hex("10010"));  // 0x12
        System.out.println(bin2Hex("111011")); // 0x3B
    }

    // 2진법 16진법으로 변환하는 method
    public static String bin2Hex(String binary){

        // 4자리씩 끊을 수 있도록 맞추어 준다.
        StringBuilder add = new StringBuilder();
        if(binary.length() % 4 != 0){
            for(int i=0; i < 4 - binary.length() % 4; i++){
                add.append("0");
            }
        }
        String bin = add.toString() + binary; // 4자리씩 끊기는 2진법 수
        StringBuilder hex = new StringBuilder(); // 16진법 변환 결과 값

        // 4개 글자씩 끊어서 2진법 -> 16진법 변환 수행
        for(int i=0; i < bin.length() / 4; i++){
            String sub = bin.substring(i*4, i*4+4); // 4개 글자로 끊는다.

            int sum = 0; // 10진수로 더해서 어떤 값인지 확인
            for(int j=0; j< sub.length(); j++){
                sum += (sub.charAt(j) - '0') * (int)Math.pow(2, 4-1-j);
            }
            if(sum > 9) hex.append((char)(sum - 10 + 'A')); // 10 이상이면 문자로 변환
            else hex.append(sum); // 10미만이면 숫자 바로 적용
        }
        // 16진수임을 표시하기 위해 앞에 0x를 붙임.
        return "0x" + hex.toString();
    }
}

 

 

 

 

관련 백준 알고리즘 문제

1373번 :  www.acmicpc.net/problem/1373
1212번 : www.acmicpc.net/problem/1212
11005번 : www.acmicpc.net/problem/11005
2745번 : www.acmicpc.net/problem/2745
11576번 : www.acmicpc.net/problem/11576

글 읽어주셔서 감사합니다.

오류가 있으면 수정하겠습니다.

반응형