백준 10757 큰수 A+B[JAVA]

Ga0·2023년 4월 3일
0

baekjoon

목록 보기
18/125

문제 해석

  • 10757번 문제는 어려운 문제는 아니지만 새로운 객체인 BigDecimal을 사용했기 때문에 정리하고자 포스트를 결심했다!
  • 문제 자체는 두 수를 입력받아서 더한 값을 출력하면 되는 문제이다!

BigDecimal

  • BigDecimalJAVA에서 숫자를 정밀하게 표현할 수 있는 유일한 방법으로, 소숫점을 저장할 수 있는 가장 큰 타입인 double은 소수점의 정밀도에 대한 한계점이 있어 데이터가 유실될 수 있다.
    -> 이를 보완하게 나온 것이 바로 BigDecimal이다

    • 소수점의 정밀도는 돈을 다루는 은행에선 매우 중요하기에 선택이 아닌 필수다! (은행말고도 세세하게 숫자를 다뤄야하는 분야라면!)
    • 하지만, 세세한 나머지 사용법이 조금 불편하고, 속도가 느리다. (아래 결과를 보면 한눈에 볼 수 있을 것이다.)

    BigDecimal 기본 용어

    - precision : 숫자를 구성하는 전체 자리수이지만, 왼쪽 부터 0이 아닌 수로 시작하여 오른쪽부터 0이 아닌 수로 끝나는 위치까지의 총 자리수이다.
    	ex) 012345.67890라고 했을 때 11이 precision는 11이 아닌 9이다.
    - scale : 전체 소수점 자리수이지만, 소수점 첫째자리부터 끝 소수점자리가 0이 아닌 것으로 끝날때까지의 자리수이다.
    	ex) 012345.67890라고 했을 때, scale은 5가 아니라 4이다.

    BigDecimal 기본 상수

    • 보통 우리가 쓰는 double, float 타입(자료형)과는 다르게 BigDecimal 타입(자료형)은 초기화가 매우 번거로운 편이다. 그래서 자주 쓰는 0, 1, 100은 쓰기 편하도록 미리 상수로 정의되어있다.
	//0
  	BigDecimal.ZERO
  
  	//1
  	BigDecimal.ONE
  
  	//10
  	BigDecimal.TEN

BigDecimal 초기화

- double 타입으로 부터 BigDecimal 타입을 초기화하는 방법으로 가장 안전한 방법은 *문자열의 형태로 생성자에게 전달하는 것이다!

import java.math.BigDecimal;

public class Main {
    public static void main(String[] args) {
        //0.000010000000000000000818030539140313095458623138256371021270751953125 값을 가짐
        //하지만 우리가 기대한 값은 그대로의 값인 0.00001이다.
        System.out.println("double을 사용한 경우 : " + new BigDecimal(0.00001));

        //위의 문제를 해결하기 위해
        System.out.println("String 사용한 경우 : " + new BigDecimal("0.00001"));
    }
}
  

결과

BigDecimal 설명

  • 더 자세한 내용은 이분께서 정말 잘 설명해주셨다.

코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.util.StringTokenizer;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br  = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        br.close();

        //(0 < A,B < 10^10000) : 자료형 BigDecimal 을 사용
        BigDecimal A = new BigDecimal(st.nextToken());
        BigDecimal B = new BigDecimal(st.nextToken());

        //BigDecimal는 숫자를 정밀하게 저장하표현할 수 있는 객체
        //단점 :  느린 속도 & 복잡한 사용법
        System.out.println(String.valueOf(A.add(B))); //A+B식으로 하지 못한다. add() 메서드를 사용해야함
    }
}

결과

  • 앞에 설명한 BigDecimal의 단점을 바로 보여준 결과다.
  • 두 큰 수를 더할 뿐인데 시간을 정말 많이 잡아먹는다.

코드2(참고)

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

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        StringTokenizer st = new StringTokenizer(br.readLine());
        StringBuilder sb = new StringBuilder();
        br.close();
        
        String A = st.nextToken();
        String B = st.nextToken();

        int flag = 0; //다음 자리수 증가하는지 마는지(올림 더하기)

        //뒤부터 더해야 한다
        for(int i = A.length()-1, j = B.length()-1; i >= 0 || j >= 0; i--, j--){
            int num = flag;

            if(i >= 0) num += A.charAt(i) - '0';

            if(j >= 0) num += B.charAt(j) - '0';

            if(num < 10){ //두 수를 더했을때 10보다 작으면 자리올림X
                flag = 0;
            }else{ //두 수를 더했을 때 10보다 크면 다음 자리수 올리고,해당 num에 10을 빼준다.
                flag = 1;
                num -= 10;
            }

            sb.append(num);
        }

        if(flag == 1){ //반복문이 끝났고 flag가 1인 경우는 마지막으로 자리 올림을 해줘야하는 것!
            sb.append(1);
        }

        System.out.println(sb.reverse()); //계산을 일의자리수부터 했기 때문에 순서를 뒤집어야한다.
    }
}

결과2

  • 2배 가량 줄었다.(속도가)
  • 메모리도 적게 쓰는 것을 확인 할 수 있다.

느낀점

  • 문제 자체는 쉬웠지만, 처음보는 객체 BigDecimal을 알아볼 기회가 되었는데, 그냥 그렇게 쓰면 된다라고만 이해했고, 정확하게는 이해하지 못했다.
  • 그래도 언제 쓸 날이 오면, 그 때는 지금보다 더 확실하게 알 수 있을까 싶다.
  • 아무튼! 굳이 필요없는 상황이면 BigDecimal은 쓰지 않는 것이 좋겠다는 생각을 했다.
  • 속도가 너어무 느리다...

0개의 댓글