티스토리 뷰

오버플로우


산술 연산을 할 때 주의할 점은 충분히 표현 가능한 산출 타입인지 확인해야 한다. 산출 타입으로 표현할 수 없는 값인 경우 오버플로우가 발생하여 쓰레기 값이 반환된다.

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);
	}
}

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
링크
«   2024/05   »
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 31
글 보관함