티스토리 뷰
오버플로우
산술 연산을 할 때 주의할 점은 충분히 표현 가능한 산출 타입인지 확인해야 한다. 산출 타입으로 표현할 수 없는 값인 경우 오버플로우가 발생하여 쓰레기 값이 반환된다.
public class OverflowExample {
public static void main(String[] args) {
int x = 50000;
int y = 50000;
int z = x * y;
System.out.println(z);
}
}
변수 x, y는 int 타입이고 z 역시 int 타입이다. 컴파일 에러도 없다. 하지만 변수 z에 예상한 값이 저장되지 않는다. 그 이유는 int 타입 범위를 초과하였기 때문이다. 올바른 값을 얻기 위해서는 변수가 long 타입이어야 한다.
public class OverflowExample {
public static void main(String[] args) {
long x = 50000;
long y = 50000;
long z = x * y;
System.out.println(z);
}
}
정확한 계산은 BigDecimal
정확한 계산을 해야 할 때는 부동소수점(실수) 타입을 사용하지 않는 것이 좋다.
public class AccuracyExample {
public static void main(String[] args) {
int x = 1;
double y = 0.1;
int num = 7;
double result = x - num * y;
System.out.println(result);
}
}
결과를 보면 result 변수의 값은 0.29999999999999993이다. 예상한 0.3이 되지 않는다. 이것은 이진 포멧의 가수를 사용하는 부동소수점 타입(float, double)은 0.1을 정확히 표현할 수 없어 근사치로 처리하기 때문이다.
public class AccuracyExample2 {
public static void main(String[] args) {
int x = 1;
int y = x * 10;
int num = 7;
double result = (y - num) / 10.0;
System.out.println(result);
}
}
정확한 값은 나오지만 매번 이렇게 int 형으로 바꾸어 계산하여 다시 부동소수점으로 표현하기는 불편하다. 하지만 우리에게는 자바 API가 있지 않은가. 그것은 바로 BigDecimal이다.
import java.math.BigDecimal;
public class BigDecimalExample {
public static void main(String[] args) {
BigDecimal decimal = BigDecimal.valueOf(1);
BigDecimal decima2 = BigDecimal.valueOf(0.7);
System.out.println(decimal.subtract(decima2));
}
}
BigDecimal을 사용하여 연산 시에는 정확한 수치 표현이 가능하다. java.math 패키지에 포함되어있다. 주의사항은 BigDecimal은 String 생성자를 사용해야 정확한 수치 표현이 가능하다. 자주 사용하는 함수는 아래와 같다.
BigDecimal | 함수 | 설명 |
add(BigDecimal augend) | 덧셈 연산 | |
subtract(BigDecimal subtrahend) | 뺄셈 연산 | |
multiply(BigDecimal multiplicand) | 곱셈 연산 | |
divide(BigDecimal divisor) | 나눗셈 연산 | |
remainder(BigDecimal divisor) | 나머지 연산 |
Infinity와 NaN 연산
/ 또는 % 연산자를 사용 시 주의해야 할 점이 있다. 0으로 나누는 경우이다. 컴파일은 정상적으로 되지만, 실행 시 ArithmeticException이 발생한다.
- 5 / 0 -> ArithmeticException 발생
- 5 % 0 -> ArithmeticException 발생
하지만 실수 타입인 0.0 또는 0.0f로 나누면 ArithmeticException이 발생하지 않고, / 연산의 결과는 Infinity(무한대) 값을 가지며, % 연산의 결과는 NaN(Not of Number)을 가진다.
- 5 / 0.0 -> Infinity
- 5 % 0.0 -> NaN
Infinity 또는 NaN 값이 나오면 어떤 연산을 해도 Infinity와 NaN이 산출된다.
- Infinity + 5 -> Infinity
- NaN + 5 -> Nan
연산 결과가 Infinity 또는 NaN 인지 확인하려면 Double.isInfinite()와 Double.isNaN() 메서드를 사용하면 된다.
public class InfinityAndNaNChecklExample {
public static void main(String[] args) {
int x = 5;
double y = 0.0;
double inf = x / y;
double nan = x % y;
System.out.println(Double.isInfinite(inf));
System.out.println(Double.isNaN(nan));
System.out.println(inf + 3);
System.out.println(nan + 3);
}
}
'프로그래밍 > Back end' 카테고리의 다른 글
[Back end] Spring log4j, logback 중복 로그 (0) | 2019.07.08 |
---|---|
[Back end] Java RestTemplate 예제 (Get&Post&Put&Delete) (0) | 2019.07.05 |
[Back end] Java의 특징 (0) | 2019.05.19 |
[Back end] Java 접근 제어자 및 각종 제어자 (0) | 2019.05.10 |
[Back end] Java interrupt() 메서드는 절대적인 것이 아니다. (0) | 2019.05.09 |
- SQL
- React
- 경력관리
- Linux 명령어
- 회고
- javascript
- Tomcat
- Eclipse
- effective java
- Java
- 프로그래머스
- 오라클
- 정렬 알고리즘
- Collection
- 자바
- sort algorithm
- Maven
- 리액트 16
- spring
- 성능분석
- 리액트
- 제주도 여행
- 오라클 내장 함수
- 자바스크립트
- 프로그래머
- 소프트웨어공학
- 제주도 3박4일 일정
- 개발환경
- 이직
- 리눅스 명령어
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |