. Java의 정석

[Java] 사칙연산시 주의사항 #1

박인영 2021. 7. 7. 02:29

 

 

 

큰 데이터타입의 값을 작은 데이터타입의 변수에 저장하려면?

 

이항 연산자의 산술 변환에서 학습 했듯이

사칙연산시 피연산자의 값 손실을 최소화하기 위해 

보다 큰 타입으로 두 피연산자의 타입을 자동으로 같게 일치시킨다.

long + int → long + long → long
float + int → float + float → float
double + float → double + double → double
 
피연산자의 타입이 int보다 작은 타입이면 자동으로 int로 변환된다.

byte + short → int + int → int
char + short → int + int → int

 

 

 

위에서 a + b는 피연산자의 타입이 int 보다 작은 byte 타입이기 때문에

결과가 int 타입으로 자동 형변환되었다.

 

하지만 변수 c는 int보다 작은 byte 타입이므로 컴파일 에러가 발생한다.

큰 데이터타입의 값을 작은 데이터타입의 변수에 저장하려면

명시적으로 형변환 연산자를 사용해서 변환해주어야 한다.

 

만약 변수 c에 byte 타입으로 저장되어야 한다면 아래와 같이 수정한다.

byte a = 10;
byte b = 20;
byte c = (byte)(a + b);
System.out.println(c);

 

또는 변수 c에 int 타입으로 저장되어야 한다면 아래와 같이 수정한다.

byte a = 10;
byte b = 20;
int c = a + b;
System.out.println(c);

 

 

 

 

 

 

 

<10 * 30을 얼마인가? >

 

int a = 10;
int b = 30;
int c = a*b;
System.out.println(c);	// 300

 

300이다.

그러나 int 타입이 아닌 byte 타입으로 바꿔서 실행한다면?

 

 

44가 출력된다. 

 

앞서 배운 것처럼 a + b는 피연산자의 타입이 int 보다 작은 byte 타입이므로

결과가 int 타입으로 자동 형변환되었고

형변환 연산자를 이용해 byte 타입으로

명시적 형변환하여 컴파일 에러는 발생하지 않는다.

 

하지만  300이 출력되지 않는다. 왜일까?

 

 

 

300은 byte 데이터 타입 변수에 저장 가능한 값의 범위가 아니기 때문이다.

그렇다면 값의 범위가 아니라고 에러가 나지 않고 44가 출력된 이유는?

 

 

 

컴퓨터가 값을 저장할 때 2진수로 저장하며

데이터 타입별로 저장되는 자릿수가 다른 점 때문이다.

 

 

 

 위 표에서 알 수 있듯이 byte 타입에서 int 타입으로 변환하는 것은

2진수 8자리에서 32자리로 변환하는 것이기 때문에 값 손실이 일어나지 않는다.

( 작은 타입에서 큰 타입으로 변환시 빈 자릿수는 양수의 경우 0, 음수의 경우 1로 채운다.)

 

반대로 int 타입을 byte 타입으로 변환하는 경우 앞의 24자리는 손실되고

하위 8자리만을 저장된다.

저장된 2진수 101100는 10진수 44가 저장되는 것이다.

 

 

 

chap02 변수에서 정수형의 오버플로우(overflow)에서 배웠던 내용으로도 설명이 가능하다.

300이라는 수는 byte에서 최대값 127에서 173만큼 오버플로우 된 값이기도 하다.

int bytemax = Byte.MAX_VALUE;			// byte의 최대값
int overflow = a * b - bytemax;			// overflow된 정도
System.out.println(overflow);				// 173
System.out.println((byte)(bytemax + overflow));	// 44