BigDecimal
문제
: 실수 계산 시 정확한 값이 출력되지 않는다.
double d1 = 0.10000000000000000009;
double d2 = 0.0000000000000000001;
System.out.println("d1 - d2 = " + (d1 - d2));
-출력-
d1 - d2 = 0.1 //예상 출력값 = 0.09999999999999999999
원인
: Java는 IEEE 754 부동 소수점 방식을 사용해 정확한 실수가 아니라 근사치를 저장한다.
해결책
: java.math.BigDecimal 클래스
- 정수 값과 정밀도(소수점 이하 자릿수)를 따로 저장해 정수 값으로 연산 후 정밀도를 적용한다.
//double d1 = 0.10000000000000000009;
//double d2 = 0.0000000000000000001;
BigDecimal d1 = new BigDecimal("0.10000000000000000009");
BigDecimal d2 = new BigDecimal("0.0000000000000000001");
//System.out.println("d1 - d2 = " + (d1 - d2));
System.out.println("d1 - d2 = " + d1.subtract(d2));
-출력-
d1 - d2 = 0.09999999999999999999
BigDecimal
1. BigDecimal 클래스 내부 일부
example: 5.0143
- intVal
: unscaledValue()에 의해 소수점 정보가 배제된 정수를 담은 BigInteger 객체가 저장된다.
// 50143
- scale
: scale()에 의해 소수점 자리수를 저장한다.(소수점 첫째 자리 ~ 오른쪽부터 0이 아닌 수로 끝나는 위치)
// 4
- precision
: precision()에 의해 총 자리수를 저장한다.(왼쪽이 0이 아닌 수로 시작하는 위치 ~ 오른쪽이 0이 아닌 수로 끝나는 위치)
// 5
- signum()
: 부호를 저장한다
// 1
2. 선언
: BigDecimal 이름 = new BigDecimal("값");
- import java.math.BigDecimal 필요
- 파라미터를 String으로 받는 이유: 오차가 발생할 수 있기 때문이다. //정확도
3. 연산
: 메서드 활용
example: n1, n2 연산
1) 덧셈
: n1.add(n2);
2) 뺄셈
: n1.subtract(n2);
3) 곱셈
: n1.multiply(n2);
4) 나눗셈
: n1.divide(n2, scale, roundingMode);
- 반올림 처리: RoundingMode의 상수 이용
상수 | 역할 |
.CEILING | 올림 |
.FLOOR | 내림 |
.UP | 양수: 올림, 음수: 내림 |
.DOWN | 양수: 내림, 음수: 올림 |
.HALF_UP | 반올림(5 이상: 올림, 5 미만: 버림) |
.HALF_EVEN | 반올림(반올림 자리값 짝수: HALF_DOWN, 홀수: HALF_UP) |
.HALF_DOWN | 반올림(5 이상: 올림, 5 미만: 버림) |
.UNNECESSARY | 나눗셈 결과 딱 안 떨어지면 ArithmeticException 발생 |
- 소수점 위치 변경
5) 나머지
: n1.remainder(n2); // 결과값 음수여도 리턴
: n1.mod(n2); // 결과값 음수면 ArithmeticException
6) 비교
: n1.compareTo(n2);
- n1 < n2: -1
- n1 == n2: 0
- n1 > n2: 1
4. 형변환
example: n1 형변환
1) int
: n1.intValue();
2) long
: n1.longValue();
3) float
: n1.floatValue();
4) double
: n1.doubleValue();
5) String
: n1.toString();
5. 기본 상수
1) 0
: BigDecimal.ZERO;
2) 1
: BigDecimal.ONE;
3) 10
: BigDecimal.TEN;