글 작성자: bbangson
반응형

개요

코딩 테스트에서 진법 변환 문제가 나왔습니다.

여러 조건 때문에 결국 못 풀어서 한이 남아 아예 프로젝트를 하나 만들고 포스팅으로 박제하고자 합니다.

 

한번 익혀두면 잊어버리지 않으니, 공부하면 좋은 지식이 될 거라 생각합니다. 

 

N진수를 입력 받아 N진수K진수로 변환하는 방법을 알아보겠습니다.

ex) 1111(2) -> 17(8)

 

N = (2 ~16) 진수 

K = (2~16)진수

 

 

 

NotationConversion

NotationConversion은 제가 지은 프로젝트 이름입니다.

 

N진수K진수로 바꾸는 변환 과정은 다음과 같습니다.

N진법으로 표기된 숫자를 10진법으로 바꾸고 바꾼 10진수를 K진법으로 바꿔줬습니다. 

 

자바 코드로 먼저 확인해보겠습니다.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/*
 N진수를 받아 K진법으로 만드는 프로젝트 
 2진수 ~16진수를 입력받아,  2진수 ~16진수로 변환해주는 프로그램
 진수를 입력받고 10진수로 변환한 다음, 다시 원하는 진수로 변환시켜보자.
*/

public class NotationConversion {
	public static void main(String[] args) throws IOException {

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		System.out.println("몇 진수를 입력하시겠습니까? (2~16만입력만 가능합니다.)");
		int N = Integer.parseInt(br.readLine());
		
		System.out.println("수를 입력해 주세요. 10이상은 대문자를 입력하십시오.");
		String number = br.readLine();

		// 먼저 입력 받은 각각의 진수를 10진법으로 바꿔준다. 
		int decimal = toDecimal(N, number);

		System.out.println("몇 진수로 바꾸시겠습니까?");
		int K = Integer.parseInt(br.readLine());
		
		String answer = conversionToK(decimal, K);
		
		System.out.print("결과 : " + answer);
	}
	
    // N진수를 10진수로 변환.
	public static int toDecimal(int N, String number) {
		
		int result = 0;
		// 입력이 10진법인 경우 바로 리턴 
		if(N == 10) {
			return Integer.parseInt(number);
		}
		else if(N >= 2 && N <= 16){
			char[] num = number.toCharArray();
			/*
			 0부터 시작하여 진수와 곱해주고 각 자리 수 숫자를 더해준다. 그리고 그 결과를 다음 자리수로 갈 때 진수와 곱해주고 현재 자리수 값을 더해준다. 반복. 
			 */
			for(int i=0; i<num.length; i++) {
				if(!errorCheck(num[i], N)) {
					System.out.println("잘못된 입력입니다. 프로그램을 다시 실행하십시오.");
					System.exit(0);
				}
				// 10이상의 숫자는 'A'를 빼고 +10을 해주면 된다. 
				if(num[i] >= 'A') {
					result = result * N + (num[i] - 'A' + 10);
				}
				else {
					result = result * N + (num[i] - '0'); 
				}
			}
		}
		else {
			System.out.println("계산할 수 없는 진수입니다. 프로그램을 다시 실행하십시오.");
			System.exit(0);
		}
		
		return result;
	}
	
    // 10진수를 K진수로 변환.
	public static String conversionToK(int decimal, int K) {
		StringBuilder sb = new StringBuilder();
		
		int current = decimal;
		
		while(current > 0) {
			// N진법으로 나누었는데 10보다 작으면 바로 추가 
			if(current % K < 10) {
				sb.append(current % K);
			}
			
			// 10이상은 알파벳으로 표기한다. 
			else {
				// 10진수를 구해주는 법과 반대로 수행해주면 된다. 10이상의 수부터 표현할 수 있기 때문에 10을 빼주는 것이다. 
				sb.append((char)(current % K - 10 + 'A'));
			}
			current /= K;
		}
		return sb.reverse().toString();
	}
	
	
	// 주어진 진법 보다 높은 숫자가 입력으로 들어오면 오류.
	public static boolean errorCheck(char num, int notation) {
		int n = 0;
		if(num >= 'A') {
			n = num - 'A' + 10;
		}
		else {
			n = num - '0';
		}
		
		if(n >= notation) {
			return false;
		}
		return true;
	}	
}

Step 1. 입력받은 N진수를 10진수로 변환.

N진수에서 10진수로 변환할 때, 각 자릿수마다 10진수 결과에 N을 곱해주면서 각 자릿수의 값을 더해주는 방식으로 해결했습니다.

맨 마지막 자릿수(일의 자리)는 0승을 곱해주기 때문에 처음 시작할 때의 result 값을 0으로 설정해줬습니다.

 

1111(8)을 10진수로 변환하는 과정을 표로 보여드리겠습니다. 1111(8) = 585(10)

i num[i] result = result * 8 + (num[i])
0 1 1 = 0 * 8 + (1)
1 1 9 = 1 * 8 + (1)
2 1 73 = 9 * 8 + (1)
3 1 585 = 73 * 8 + (1)

 

 

Step2. 10진수를 K진수로 변환.

10진수K진수로 변환하는 방법은 간단합니다. 수학적으로는 10진법으로 표기된 숫자를 K로 나누어 그 나머지를 표시하고 더 이상 나누어지지 않을 때까지 반복하면 됩니다. 

 

여기서 주의할 점은 일반적으로 String 타입으로 정답을 도출해 낼 것입니다. 이 과정에서 최종 String값reverse()해줘야 정상적인 답이 도출됩니다.  

 

 

 

BinaryToHexadecimal (2진법 -> 16진법)

10진법의 변환 과정을 거치지 않고 2진법에서 16진법으로 바로 바꾸는 방법입니다.

 

이 방법은 자주 출제되고 여기저기 노출되는 유형이기 때문에 정리하겠습니다.

사실 이 메소드를 구현하는 것이 코딩 테스트에 나왔었는데, 하 너무 아쉽습니다.

 

정말 간단합니다. 

 

16^1 = 2^4인 점을 생각한다면,

2진수의 4비트가 16진수의 1비트를 나타내는 원리를 이용하는 것이 핵심 포인트입니다.

 

코드로 확인하겠습니다.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class binary2Hex {

	// 2진법 -> 16진법 변환하기
	public static void main(String[] args) throws IOException {
		
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		System.out.print("2진수를 입력하십시오 : " );
		String binary = br.readLine();
		
		System.out.println(binToHex(binary));
	}
	
	public static String binToHex(String binary) {
		String answer = "";
		StringBuilder sb = new StringBuilder();
		
		int length = binary.length();
		// 4로 나누어 떨어질 때까지 0을 앞에다 추가해준다. 
		// 4자리로 끊기 위함.
		while(length % 4 != 0) {
			sb.append("0");
			length++;
		}
		
		binary = sb.toString() + binary;
		
		// 전체 길이에서 4로 나눠줌으로써 총 반복횟수 결정.
		for(int i=0; i<length / 4; i++) {
			// 4자리씩 끊은 2진수 저장. 
			String subBinary = binary.substring(i*4, i*4+4);
			int Hex = 0;
			
			// 10진법의 수를 K진법으로 바꾸는 방법과 유사. 
			// 앞에서부터 진법을 차례대로 곱해가면서 현재 자리의 수를 더해준다.
			for(int j = 0; j<subBinary.length(); j++) {
				char num = subBinary.charAt(j);
				if(num >= '0' && num <= '9') {
					Hex = Hex * 2 + (num-'0');
				}
				else {
					Hex = Hex * 2 + (num - 'A' + 10);
				}
			}
			
			if(Hex >= 10) answer += (char)(Hex - 10 + 'A');
			else answer += Hex;
		}
		return "0x"+answer;
	}
}

주의사항

☞   2진수는 4자리씩 끊어지지 않을 수 있습니다.

- (16진수의 길이) % 4 == 0이 될 때까지, 기존 16진수 앞에 "0"을 붙여줍니다.

 

☞  4자리씩 끊어서 나온 2진수의 각 자릿수 합을 16진수의 한 자릿수로 바꿔줍니다.

-  예를 들어, 28(10) = 11100(2)

-> "0" 추가

-> 0001 1100

-> 4자리씩 10진수 도출 = 1, 12

-> 16진수로 변환 = 1, C

 

☞  16진수임을 표시하기 위해 앞에 "0x"를 붙여줍니다.

-> "0x" 추가

= 0x1C     

 

 

 

※ 간단하게 진행한 알고리즘 토이 프로젝트라 미흡하고 오류가 많을 수 있습니다. 피드백은 환영합니다.

 

 

반응형