타입 | 범위 |
---|---|
long | 1.4E-45 ~ 3.4028235E38 |
double | 4.9E-324 ~ 1.7976931348623157E308 |
Java의 long
, double
자료형은 부동 소수점을 사용하기 때문에 내부적으로 수를 저장할 때 이진수의 근사치를 저장한다. 따라서 소수점 이하 사칙연산 시 오차가 발생하여 정확한 값을 보장하지 않는다.
double value1 = 12.23;
double value2 = 34.45;
// 기대값 : 46.68
System.out.println(value1 + value2); // 46.68000000000001
위의 예제에서도 결과값으로 46.68
이 출력될 것 같지만 실제로 46.68000000000001
이 출력된다. 소수점을 정확하게 표현하는 것이 아니라 근사값으로 처리하기 때문이다. 이렇듯, 컴퓨터에서의 실수 표현은 근사값을 표현하는 것으로 이해해야 한다.
→ 이러한 문제 때문에 숫자에 민감한 금융 거래, 소수점 단위의 정확한 연산이 필요할 때는 BigDecimal
을 사용한다.
BigDecimal
을 사용해야 한다.
BigDecimal
객체 생성 시String
으로 생성해야 한다.
double
로 생성하면 Java가 double
근사치를 BigDecimal
에 넘겨주게 되어 오차가 발생할 수 있다.import java.math.BigDecimal; // math 클래스 import
// 문자열로 생성
BigDecimal bigDecimal = new BigDecimal("123.45678");
// double 타입으로 초기화하는 방법 - valueOf
// 내부적으로 생성자 + 문자열을 사용한다.
BigDecimal bigDecimal2 = BigDecimal.valueOf(123.456);
// 아래처럼 사용하지 말것!!!!
// 12.230000000000000426325641456060111522674560546875
BigDecimal bigDecimal3 = new BigDecimal(12.23);
BigDecimal
은 문자열이기에 사칙연산이 불가능하다. 따라서 BigDecimal
클래스의 메서드를 사용해야 한다.
연산 | 메서드 |
---|---|
+ | bigDecimal.add(BigDecimal val) |
- | bigDecimal.subtract(BigDecimal val) |
* | bigDecimal.multiply(BigDecimal val) |
/ | bigDecimal.divide(BigDecimal val) |
% | bigDecimal.remainder(BigDecimal val) |
toPlainString()
메서드를 통해2.0E7
과 같은 지수(E) 표현을 제거할 수 있다.
// toPlainString() : 생성자로 전달받은 값을 지수 표현없이 반환한다.
public void toPlainString() {
System.out.println(new BigDecimal("2564000").toPlainString()); // 2564000
System.out.println(new BigDecimal("2.564E6").toPlainString()); // 2564000
}
Q.
A.