Java 기본형 4

2021. 6. 1. 18:00Java

정수형의 선택기준

변수에 저장하려는 정수형의 범위에 따라 4개의 정수형 중에서 하나를 선택하면 되겠지만, byte나 short보다 int를 사용하도록 하자. byte와 short이 int보다 크기가 작아서 메모리를 조금 더 절약할 수는 있지만, 저장 할 수 있는 값의 범위가 작은 편이라서 연산시에 범위를 넘어서 잘못된 결과를 얻기가 쉽다. 그리고 JVM의 피연산자 스택(operand stack)이 피연산자를 4byte단위로 저장하기 때문에 크기가 4byte보다 작은 자료형(byte, short)의 값을 계산할 때는 4byte로 변환하여 연산이 수행된다. 그래서 오히려 int를 사용하는 것이 더 효율적이다. int 타입의 크기는 4byte(= 32bit)이므로, 표현할 수 있는 정수의 개수는 약 40억이며, 표현가능한 정수의 범위는 20억이다.

2의10승 = 1024 = 10의3승이므로, 2의32승 = 2의10승 x 2의10승 x 2의10승 x 2의2승 = 1024 x 1024 x 1024 x 4 ≒ 4 x 10의9승

 

결론적으로 정수형 변수를 선언할 때는 int타입 으로 하고, int타입으로 하고, int의 범위(약 +- 20억)을 넘어서는 수를 다뤄야할 때는 long을 사용하면 된다. 그리고 byte나 short은 성능보다 저장할 공간을 절약하는 것이 더 중요할 때 사용하자.

정수형 변수 선언 할때 int
int의 범위를 넘어갈 때 long
저장공간을 절약해야 할 때 byte, short

long타입의 범위를 벗어나는 값을 다룰 때는 실수형 타입이나 BigInteger클래스를 사용하면 된다.

정수형의 오버플로우

만일 4bit 2진수의 최대값인 1111에 1을 더하면 어떤 결과를 얻을 수 있을까? 4bit의 범위를 넘어서는 값이 되기 때문에 에러가 발생할까?

원래 2진수 1111에 1을 더하면 10000이 되지만 4bit로는 4자리의 2진수만 저장할 수 있기 때문에 0000이 된다. 즉 5자리의 2진수 10000중에서 하위 4bit만 저장하게 되는것이다. 이처럼 연산과정에서 해당 타입이 표현할 수 있는 값의 범위를 넘어서는 것을 오버플로우(overflow)라고 한다. 오버플로우가 발생했다고 해서 에러가 발생하는 것은 아니다. 다만 예상했던 결과를 얻지 못할 뿐이다. 애초부터 오버플로우가 발생하지 않게 충분한 크기의 타입을 선택해서 사용해야 한다.

 

오버플로우는 '자동차 주행표시기'나 '계수기'등 우리의 일상생활에 서도 발견할 수 있는데 네 자리 계수기라면 0000부터 9999까지 밖에 표현하지 못하는므로 최대값인 9999다음의 숫자는 0000이 될 것이다. 원래는 10000이 되어야하는데 다섯 자리는 표현할 수 없어서 맨 앞의 1은 버려지기 때문이다. 그러면 이번엔 반대로 최소값인 0000에서 1을 감소시키면 어떤 결과를 얻을까? 0에서 1을 땔 수 없으므로 0000앞에 저장되지 않은 1이 있다고 가정하고 뺄셈을 한다.

결과는 10진수 1 0 0 0 0 - 1 = 9 9 9 9, 2진수는 1 0 0 0 0 - 1 = 1 1 1 1

이는 마치 계수기를 거꾸로 돌리는 것과 같다. 0000에서 정방향으로 돌리면 0001이 되지만 역방향으로 돌리면 9999가 되는 것이다.

TV의 채널을 증가시키다가 마지막 채널에서 더 증가시키면 첫 번째 채널로 이동하고, 첫 번째 채널에서 채널을 감소시키면 마지막 채널로 이동하는 것과 유사하다.

 

그래서 정수형 타입이 표현할 수 있는 최대값에 1을 더하면 최소값이 되고 최소값에서 1을 빼면 최대값이 된다.

최대값 + 1 → 최소값
최소값 - 1 → 최대값

부호있는 정수의 오버플로우

부호없는 정수와 부호있는 정수는 표현범위 즉, 최대값과 최소값이 다르기 때문에 오버플로우가 발생하는 시점이 다르다. 부호없는 정수는 2진수로 0000이 될 때 오버플로우가 발생하고 부호있는 정수는 부호비트가 0에서 1이 될때 오버플로우가 발생한다.

오버플로우를 이용한 예제
출력결과

short타입과 chart타입의 최대값과 최소값에 1을 더하거나 뺀 결과를 출력하였다. 실행결과를 좀더 이해하기 쉽게 정리하자면 다음과 같다.

sMin - 1 → sMax // 최소값 - 1 → 최대값
sMax + 1 → sMin // 최대값 + 1 → 최소값
cMin - 1 → cMax // 최소값 - 1 → 최대값
cMax +1 → cMin // 최대값 + 1 → 최소값

 

최소값에서 1을 빼면 최대값이 되고, 최대값에 1을 더하면 최소값이 된다는 것읋 확인 할 수 있다.

'short'과'char'의 크기는 모두 16bit이므로 표현할 수 있는 값의 개수 역시 2의16승개(65536개)로 같다. 그러나 short은 이 중에서 절반(32768개)을 음수를 표현하는데 사용하고 char는 전체(65535+1개)를 양수(65535)와0(1개)을 표현하는데 사용한다.

16비트로 표현할 수 있는 정수의 개수: 2의16승개(65536개)
short타입의 표현범위: -2의15승 ~ 2의15승-1(-32768 ~ 32765)
chart타입의 표현범위: 0 ~ 2의16승 - 1(0 ~ 65536)

'Java' 카테고리의 다른 글

Java 2의보수법  (0) 2021.06.10
Java 기본형 5  (0) 2021.06.02
Java 기본형 3  (0) 2021.05.31
Java 기본형 2  (0) 2021.05.30
Java 기본형  (0) 2021.05.29