백준에서 a^b꼴의 문제를 본 적이 있을 겁니다. 문제는 여기에서 풀어보실 수 있습니다. 물론, b는 0보다 크거나 같고 100보다는 작거나 같은 정수이고, a는 소수점 밑에 자리수가 9개까지 나올 수 있습니다. 사실, 저는 이것을 .을 기준으로 일일히 파싱해서 풀었습니다. 즉, .을 기준으로 나누면 j/m꼴이 됩니다. 그러니, (j/m)^b을 계산하는 문제로 바뀌고, m은 10^q꼴이니, j^b의 결과값에 따라서 적절히 잘 파싱하면 됩니다.

 

 그런데, 그리 한다면, j는 최대 11자리 ~ 12자리의 정수로 바뀔 거고, b는 최대 100이니, 1100자. 결국 이 문제를 제대로 풀려면 큰 수 곱셈을 잘 구현해야 한다는 이야기가 되겠습니다. 이펙티브 자바가 있다면 정확한 답이 필요하다면 float와 double은 피하라와 같이 보시면 좋겠습니다. 물론 여기를 보셔도 좋고요.

 


  BigInteger로 코딩을 하면, .에 따라서 파싱을 하고 또 결과를 가져온 다음에 적절히 파싱하는 로직이 추가되어야 합니다. 이는 매우 귀찮은 일입니다. 더 간단한 방법이 없을까요? Java에는 이러한 걱정을 할 필요가 없는 BigDecimal 클래스가 있습니다. 이것은 소수점 밑에 자리수가 꽤 큰 실수도 다룰 수 있는 구조입니다. 잘 생각해 보면, 그런 것들도 a/b꼴로 표현할 수 있고, a와 b가 BigInteger라면, 소수점 밑에 자리가 몇 자리가 되더라도 다룰 수 있거든요.

 

 실제로 BigDecimal은 내부적으로 BigInteger를 씁니다.

 

 생성자들을 보면, String을 받는 것이 있고, double을 받는 것이 있습니다. 당연하게도 String을 넘겨주어야 하는데요. double로 넘겨 보겠습니다.

 

 

 875번째 줄을 타고 들어가 보겠습니다.

 

 

 그러면 얼추 봐도, bit 값에 따라서 뭔가를 처리하고 있음을 볼 수 있습니다. 그러면, 0.1을 정확하게 저장할 수 없다면, 오차가 날 겁니다. 0.1이 어떻게 들어갔는지 보겠습니다.

 

 

 이 프로그램을 실행시켜 봅시다.

 

 

 그러면 정확히 0.1이 들어가는 것이 아니라 0.1000000000000000055511151231257827021181583404541015625라는 값이 들어가게 되는데요. 약간의 오차가 생겨버렸습니다. 이런 약간의 오차가 pow 같은 것으로 누적이 되면, 어마어마한 수치로 다가올 겁니다.

 


 그러면 어떻게 하면 될까요? 간단합니다. String으로 입력을 받아서, BigDecimal 생성자에 넣어주면 됩니다.

 

 double형 대신에 String으로 넣어주었다는 것을 보실 필요가 있습니다. 그러면 결과가 어떻게 나올까요?

 

 

 0.1이 정확하게 나옴을 알 수 있습니다. 여담으로, 문자열을 생성자로 넘겨줬을 때 흐름을 따라가 보면, 길이가 긴 메소드가 있음을 알 수 있는데요. 이는, BigInteger가 int나 long보다는 꽤 느리기 때문입니다. 그렇기 때문에, 적당히 처리 할 만 하면, int나 long으로 처리를 하고, 그렇지 않으면, BigInteger 계열로 변환하여 처리합니다.

 

 

 이제 이를 반영한 코드를 보겠습니다. 0.1 10 이렇게 들어오면, String으로 받은 다음에, split로 나눕니다. 0.1과 10은 공백으로 구분이 되어 있으므로, split의 인자에 " "을 넣었습니다. 그러면 자연스럽게 str[0]은 "0.1", str[1]은 "10"이 됩니다. 9번째 줄에 보면, 새로운 BigDecimal 객체를 생성할 때, String인 "0.1"을 넣었음을 알 수 있습니다.

 

 다음에, bd의 pow 메소드를 호출해주면 쉽게 끝날 거 같습니다.

 

 

 그런데 이건 또 무슨 일일까요? 0.1 10을 넣으니 1E-10이 뜨네요.

 

 

 toPlainString 메소드는 exponent field 없이 출력을 해 줍니다.

 

 

 프로그램을 이렇게 바꾸어 보고, 인풋 0.1 10을 넣어봅시다.

 

 

 그러면 1E-10 없이 출력이 되었음을 볼 수 있습니다. 제가 설명한 것들을 코드로 구현해서 제출하면 맞았습니다를 볼 수 있습니다.