백준 10827 : a^b (실수 제곱값의 정확한 계산, BigDecimal)
백준 10827 : URL
a^b
문제실수 a와 정수 b가 주어졌을 때, a의 b제곱을 정확하게 계산하는 프로그램을 작성하시오. 입력첫째 줄에 a와 b가 주어진다. (0 < a < 100, 1 ≤ b ≤ 100) a는 최대 소수점 9자리이며, 소수가 0으로 끝나는 경우는 없다. 출력첫째 줄에 a의 b제곱을 출력한다. 예제 입력 13.141592 3 예제 출력 131.006257328285746688 예제 입력 20.1 10 예제 출력 20.0000000001 예제 입력 31.01 5 예제 출력 31.0510100501 힌트
|
문제 분석
실수A를 정수B번 제곱한 연산(A^B)의 정확한 값을 출력하는 문제다.
JAVA에서 제곱값은 Math 클래스의 pow를 이용하는게 대부분이지만, Math.pow는 근사치를 수행하므로 정확한 값을 구할 수 없다.
실수의 제곱 연산 시 double타입의 정밀도가 최대 13자리이므로 소수표현범위를 초과하여 오차가 발생하기 때문이다.
따라서 java.math.BigDecimal 클래스를 이용해야한다.
BigDecimal클래스에서는 실수 123.456을 다음과 같이 표현한다.
1 2 3 | private final BigInteger value; private final int scale; private transient int precision; |
1 2 3 4 | Big Decimal bd = new BigDecimal("123.456"); // value = 123456 // scale = 3 // precision = 6 |
이렇게 BigDecimal은 정수를 이용해서 실수를 표현하기 때문에 실수의 정확한 표현이 가능하다.
BigDecimal을 이용한 소스코드를 작성해보면 다음과 같다. (val^scale)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import java.util.Scanner; import java.math.BigDecimal; public class Main { public static void main(String[] args) { Scanner s = new Scanner(System.in); // 실수 입력 BigDecimal val = s.nextBigDecimal(); // 정수 입력 int scale = s.nextInt(); // 제곱 연산 수행 BigDecimal result = val.pow(scale); // 출력 System.out.println(result); } } |
채점결과는 60%까지 잘가다가 오답발생..
0.1^10 의 값을 입력했을때, 1E-7 로 지수형태의 리터럴 값이 출력된다.
아마 이게 문제인듯
그렇다면, BigDecimal 객체의 toPlainString() 메서드를 이용하여 출력해보자.
toPlainString() 메서드는 BigDecimal의 지수필드가 없는 문자열 표현을 반환한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import java.util.Scanner; import java.math.BigDecimal; public class Main { public static void main(String[] args) { Scanner s = new Scanner(System.in); BigDecimal val = s.nextBigDecimal(); int scale = s.nextInt(); BigDecimal result = val.pow(scale); System.out.println(result.toPlainString()); } } |
채점결과는 정답 !
혹시나 pow() 메서드가 문제인가 해서 다른 방법을 찾아보았는데,
BigDecimal 객체의 pow 메소드 대신 multiply() 메서드를 이용하여 직접 a를 b번 곱해주는 방법도 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import java.util.Scanner; import java.math.BigDecimal; public class Main { public static void main(String[] args) { Scanner s = new Scanner(System.in); BigDecimal val = s.nextBigDecimal(); int b = s.nextInt(); BigDecimal result = BigDecimal.ONE; while(b-- > 0) { result = result.multiply(val); } System.out.println(result.toPlainString()); } } |