BigDecimal클래스?
double타입으로 표현할 수 있는 값도 범위가 넓은 편이지만 정밀도가 최대 13자리 밖에 되지 않고
실수형의 특성상 오차를 피할 수 없다.
하지만 BigDecimal을 이용한다면 더 큰 실수를 다룰수 있다.
| private final BigInteger intVal; |
| private final int scale; |
| private transient int precision |
위의 코드는 클래스 내부에 정의된 멤버변수인데 정수부분 지수부분 정밀도를 각 변수에 담아 사용하고 있다
BigDecimal에 123.45를 담는다 했을 때 12345×10−2 로 표현 가능하며
이 값이 BigDecimal에 담기면 intVal
의 값은 12345가 되고 scale
의 값은 2가 된다.
scale
의 값은 소수점 이하의 자리수를 의미한다 그리고 percision
의 값은 5가 되는데
이 값은 정수의 전체 자리수를 의미한다.
| BigDecimal val = new BigDecimal("123.45"); |
| System.out.println(val.unscaledValue()); |
| System.out.println(val.scale()); |
| System.out.println(val.precision()); |
BigDecimal의 생성
BigDecimal을 생성할 때는 문자열로 숫자를 표현하는 것이 일반적이다.
| BigDecimal val; |
| val = new BigDecimal("123.4567890"); |
| val = new BigDecimal(123.456); |
| val = new BigDecimal(123456); |
| val = BigDecimal.valueOf(123.456); |
| val = BigDecimal.valueOf(123456); |
한가지 주의할 점은 double타입의 값을 매개변수로 갖는 생성자를 사용하면
오차가 발생할 수 있다.
| System.out.println(new BigDecimal(0.1)); // 0.10000000000000000555111... |
| System.out.println(new BigDecimal("0.1")); // 0.1 |
다른 타입으로 변환
| String toPlainString() |
| String toString() |
toPlainString()
, toString()
둘 다 반환결과가 같지만
인스턴스를 생성 시 1.0e−22와 같은 지수형태의 리터럴을 사용하면 다른 결과를 얻는 경우가 있다.
| BigDecimal val = new BigDecimal(1.0e-22); |
| System.out.println(val.toPlainString); // 0.00000000000000000000010... |
| System.out.println(val.toString); // 1.000000000000000048...5E-22 |
Number로 부터 상속받은 변환 메서드들이 있다.
| BigDecimal val = new BigDecimal("123.45"); |
| val.intValue(); |
| val.longValue(); |
| val.floatValue(); |
| val.doubleValue(); |
정수형으로 변환하는 메서드 중 이름 끝에 'Exact'가 붙은 것들은 변환한 결과가
변환한 타입의 범위에 속하지 않으면 ArithmeticException을 발생시킨다.
| val.byteValueExact() |
| val.shortValueExact() |
| val.intValueExact() |
| val.longValueExact() |
| val.toBigIntegerExact() |
BigDecimal의 연산
실수형에 사용할 수 있는 모든 연산자와 계산을 쉽게 해주는 메서드가 있다.
| BigDecimal add(BigDecimal val) |
| BigDecimal subtract(BigDecimal val) |
| BigDecimal multiply(BigDecimal val) |
| BigDecimal divide(BigDecimal val) |
| BigDecimal remainder(BigDecimal val) |
연산결과의 정수, 지수, 정밀도가 달라진다.
| |
| BigDecimal bd1 = new BigDecimal("987.654"); |
| BigDecimal bd2 = new BigDecimal("1.0"); |
| BigDecimal bd3 = bd1.multiply(bd2); |
| System.out.println(bd3); |
divide(), setScale() - 반올림
나눗셈을 처리하기 위한 다양한 방법이 존재한다. 나눗셈의 결과를 반올림하는 방법을 선택 할수 있고
몇번째 자리(scale)에서 반올림 할지 정할 수 있다.
BigDecimal이 오차없이 실수를 저장한다고 해도 나눗셈의 오차는 어쩔 수 없다.
| BigDecimal bd1 = new BigDecimal("3"); |
| BigDecimal bd2 = new BigDecimal("2"); |
| BigDecimal bd3; |
| |
| bd3 = bd1.divide(bd2); // bd3 = 1.5 |
| bd1.divide(bd2, RoundingMode.HALF_UP); // 나눗셈을 한 뒤에 반올림 : 2 |
| bd3.setScale(0, RoundingMode.HALF_UP); // 1.5를 반올림 |
상수 | 설명 |
CEILING | 올림 |
FLOOR | 내림 |
UP | 양수일 때는 올림, 음수일 때는 내림 |
DOWN | 양수일 때는 내림, 음수일 때는 올림(UP과 반대) |
HALF_UP | 반올림(5이상 올림, 5미만 버림) |
HALF_EVEN | 반올림(반올림 자리의 값이 짝수면 HALF_DOWN, 홀수면 HALF_UP) |
HALF_DOWN | 반올림(6이상 올림, 6미만 버림) |
UNNECESSARY | 나눗셈의 결과가 딱 떨어지는 수가 아니면, ArihmeticException발생 |
1.0/3.0처럼 나눗셈의 결과가 무한소수인 경우, 반올림 모드를 지정해주지 않으면 ArihmeticException이 발생한다.
MathContext
반올림 모드와 정밀도를 하나로 묶은 클래스이다
| BigDecimal bd1 = new BigDecimal("123.456"); |
| BigDecimal bd2 = new BigDecimal("1.0"); |
| bd1.divide(bd2, 2, HALF_UP); |
| bd1.divide(bd2, 2, new MathContext(2, HALF_UP))); |
댓글