[JAVA] 백준 2745. 진법 변환

이 글은 읽는데 약 5분이 걸립니다.

※개인 공부 목적의 정리글입니다.
이 글의 내용이 최선의 해답은 아닐 수 있습니다.

문제

B진법 수 N이 주어진다. 이 수를 10진법으로 바꿔 출력하는 프로그램을 작성하시오.

10진법을 넘어가는 진법은 숫자로 표시할 수 없는 자리가 있다. 이런 경우에는 다음과 같이 알파벳 대문자를 사용한다.

A: 10, B: 11, …, F: 15, …, Y: 34, Z: 35

입력

첫째 줄에 N과 B가 주어진다. (2 ≤ B ≤ 36)

B진법 수 N을 10진법으로 바꾸면, 항상 10억보다 작거나 같다.

출력

첫째 줄에 B진법 수 N을 10진법으로 출력한다.

요약

주어진 숫자는 주어진 진법을 따른다. 이 진법에 따라 주어진 숫자를 10진법으로 바꾸어 출력하라.

풀이 과정

가장 많이 들어본 진법은 2, 10진법일 것이다. 컴퓨터 쪽에 지식이 어느 정도 있다면 16진법이나 8진법도 들어봤을 것이다.
그런데 당장 문제의 예제 입력에서는 36진법이라는 생소한 진법이 나온다. 어떻게 해야할까?

사실 진법은 2진법, 10진법 등 몇 개만 있는것이 아니다 12진법도 있을 수 있고, 22진법도 있을 수 있다.

진법이란 자릿수를 정하기 위한 기수법(記數法)의 하나라고 사전에 나와있다. 그렇기 때문에 진법은 자릿수가 올라가는 단위를 기준으로 한다.
예시로 10진법은 0부터 9까지 10개의 숫자가 나온 후 그 다음 숫자를 표현하기 위해서는 자릿수가 올라간다.
16진법은 0부터 F까지 16개의 숫자가 나온 후 그 다음 숫자를 표현하기 위해서 자릿수가 올라간다

우리가 일반적으로 쓰는 숫자는 10개밖에 없으므로 11진법 이상을 표현하려면 11, 12, 13, …에 해당되는 숫자를 하나의 문자로 표시해야 하므로 이른 A부터 순서대로 붙이게 된다.
이 문제에서는 이렇게 붙여 나가서 최종적으로 Z가 35를 뜻하게 된다.

진법 변환 방법

B진법으로 나타내진 수를 10진법으로 변환하는 방법은 이렇다.

16진법, A3F

16진법A3F
10진법10315
자리번호210

16진법 각 자리의 수를 10진법으로 나타내면 위와 같다. 또한 자리 번호라는 것이 있는데, 이것은 오른쪽에서 왼쪽으로 0부터 1씩 커진다. 이제 계산 식을 보자

\((10\times16^2) + (3\times16^1) + (15\times16^0) = 2623\)

보다시피 (10진법숫자 * 진법^자리번호)를 모두 더하여서 계산한다. 이걸 이제 코드로 구현하면 된다

나의 코드

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

public class Main {

    public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] input = br.readLine().split(" ");
        
        char[] N = input[0].toCharArray();  // 숫자를 입력받아 char 배열로
        int B = Integer.parseInt(input[1]);  // 무슨 진법인지
        int result = 0;  // 계산 결과 저장 변수
        

        // 글자를 배열의 인덱스 0부터 꺼내오는데 쓸 변수 i
        // 그리고 (글자의길이-1)부터 시작하는 자릿수 변수 exp(exp는 지수를 뜻한다)
        for(int i=0, exp=N.length-1; i<N.length; i++, exp--){
            int asc = (int) N[i];  // 현재 글자의 아스키코드값
            
            if('0' <= asc && asc <= '9'){  // 만약 현재 글자가 0-9이면(즉 일반 숫자이면)
                asc -= 48;  // 0의 아스키코드 값인 48을 뺀다
            }else{
                asc -= 55;  // 아니면 알파벳 대문자이다. A가 10이어야 하므로 55를 빼준다
            }
            
            result += (Math.pow(B, exp) * asc);  // 위의 진법 변환 공식을 그대로 구현한 것
        }
        
        System.out.println(result);
        br.close();
    }
}

주의점

자릿수(위 코드에서는 exp 변수)를 반대 방향으로 하지 않도록 주의하자.
변수 i와 exp를 분리한 것은 증감 방향이 서로 반대라서 같이 쓰면 헷갈리기 때문이다.

나도 처음에 같이 쓰다가 틀렸다.

댓글