핀수로그
  • [Java] 진법 변환과 BigInteger
    2022년 11월 23일 22시 04분 12초에 업로드 된 글입니다.
    작성자: 핀수
    728x90
    반응형

    들어가며

    코딩테스트 문제를 풀다보면 n진수 변환이 변변찮게 등장한다.

    이번 기회에 확실하게 정리해보려고 한다.

    진법 변환

    제공 함수로 변환하기

    n진수 -> 10진수

    Integer 클래스에서 제공하는 함수로 변환할 수 있다.

    2진수, 8진수, 16진수(Binary, Octal, Hex)를 제공한다.

    public class BinarySample {
    
        public static void main(String[] args) {
            int a = 29;
            System.out.println("Decimal -> Binary");
            System.out.println(Integer.toBinaryString(a)); // 11101
    
            System.out.println("Decimal -> Octal");
            System.out.println(Integer.toOctalString(a)); // 35
    
            System.out.println("Decimal -> Hex");
            System.out.println(Integer.toHexString(a)); // 1d
        }
    }

    Integer.toString(변환할 수, 진수)를 통하면 제공하는 진수 이외의 진법 변환도 가능하다.

    public class BinarySample {
    
        public static void main(String[] args) {
            int a = 29;
            System.out.println("Decimal -> number you want");
            System.out.println(Integer.toString(a, 2)); // 11101
            System.out.println(Integer.toString(a, 6)); // 45
            System.out.println(Integer.toString(a, 8)); // 35
            System.out.println(Integer.toString(a, 16)); // 1d
        }
    }

    10진수 -> n진수

    이번에도 역시나 Integet.toString(변환할 수, 이 수의 진법)을 통해 가능하다.

    public class BinarySample {
    
        public static void main(String[] args) {
            String binary = "11101";
            String octal = "35";
            String hex = "1d";
    
            System.out.println("Binary -> Decimal");
            // 넣은 값이 몇 진수인지 알려주면 됨
            System.out.println(Integer.parseInt(binary, 2)); // 29
            System.out.println(Integer.parseInt(octal, 8)); // 29
            System.out.println(Integer.parseInt(hex, 16)); // 29
        }
    }

    직접 구현하기

    제공되는 함수가 있어 직접 구현할 일은 없겠지만 참고용으로 작성한다.

    public class BinarySample {
    
        public static void main(String[] args) {
            int a = 29;
    
            System.out.println("직접 구현");
            System.out.println(calculateRadix(a, 2)); // 11101
            System.out.println(calculateRadix(a, 6)); // 45
            System.out.println(calculateRadix(a, 8)); // 35
            System.out.println(calculateRadix(a, 16)); // 113
        }
    
        private static String calculateRadix(int num, int radix) {
            String calculatedNum = "";
    
            while (num > 0) {
                calculatedNum = (num % radix) + calculatedNum;
                num = num / radix;
            }
            return calculatedNum;
        }
    }

    함수를 통한 16진수 변환의 결과는 1d였는데,

    직접 구현한 16진수 변환의 결과는 113이다.

    이거 다른것 아닌가? 구현이 잘못된 것 아닌가?

    아니다.

     

    16진수란 16을 기수로 하는 번호체계를 의미한다.

    16진수에서 존재하는 숫자는 아래와 같다.

    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 십, 십일, 십이, 십삼, 십사, 십오

     

    십부터 십오를 숫자로 쓰게 되면

    자리수가 두자리가 되므로 16진수에서는

    A 10

    B 11

    C 12

    D 13

    E 14

    F 15

    (대소문자 구분하지 않음)

    로 표현한다.

     

    따라서 113과 1d가 의미하는 바는 동일하다. 표기는 1d가 맞겠지만..

    16진수는 이진수를 읽기 편하게 하기 위해 사용한다.

    자세한 내용은 이 글을 참고하면 된다.

    BigInteger

    자료형 int의 경우 메모리의 크기는 4byte로 -2,147,483,648 ~ 2,147,483,647 까지 표현할 수 있다.

    long의 경우 메모리의 크기는 8byte로 -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 까지 표현할 수 있다.

    이 범위를 벗어나게 되면 모두 0으로 출력된다.

    웬만해선 이 범위를 벗어나는 수를 다룰 일은 없겠지만 만일의 경우를 대비해 무한한 정수를 사용해야할 가능성이 있다면

    BigInteger 클래스를 사용하는 것이 좋다.

    해당 클래스는 문자열 형태이기 때문에 숫자의 범위가 무한하다. 따라서 어떤 숫자든 담을 수 있다.

    import java.math.BigInteger;
    
    public class BigIntegerSample {
    
        public static void main(String[] args) {
            //Long l = 100000000000000000000; // Integer number too large
            BigInteger bigInteger = new BigInteger("100000000000000000000");
    
            // 덧셈
            System.out.println("덧셈 : "+bigInteger.add(BigInteger.valueOf(1)));
            System.out.println("뺄셈 : "+bigInteger.subtract(BigInteger.valueOf(1)));
            System.out.println("곱셈 : "+bigInteger.multiply(BigInteger.valueOf(1)));
            System.out.println("나눗셈(몫) : "+bigInteger.divide(BigInteger.valueOf(1)));
            System.out.println("나눗셈(나머지) : "+bigInteger.remainder(BigInteger.valueOf(1)));
        }
    }

    BigInteger 를 계산하기 위해서는 해당 클래스 내부 메소드를 사용해야한다.

    기본 자료형으로 변환하고 싶다면

    bigInteger.intValue() 와 같은 메소드를 사용하면 된다.

    bigInteger 끼리 비교가 필요할 때는 compareTo 메소드를 사용하면 된다.

    같은 수라면 0을, 다른 수라면 1를 리턴한다.


    References

    아래 글을 참고하여 작성 되었습니다.

    https://cornarong.tistory.com/48

    https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=silverstonec&logNo=60196870427

    https://coding-factory.tistory.com/604

    728x90
    반응형
    댓글