본문 바로가기

프로그래밍언어/JAVA

[JAVA] 형변환 (casting)

반응형

1. 형변환이란?

 

모든 변수와 리터럴에는 타입이 있다. 프로그래밍을 하다보면 서로 다른 타입간의 연산을 수행해야 하는 경우가 있는데, 이때 각 타입을 일치시켜야 하는데 변수나 리터럴의 타입을 다른 타입으로 변환하는 것을 형변환 이라고 한다.

 

 

2. 형변환 방법

 

형변환을 하는 방법은 형변환시킬 변수나 리터럴 앞에 변환하고자 하는 타입을 괄호와 함께 붙여주면 된다.

 

char id = 's';

int numId = (int)id;
// (타입) 피연산자변수
// char형 id -> int형으로 변환

 

이떄 사용되는 괄호는 캐스트 연산자 또는 형변환 연산자라고 한다.

형변환을 한다고 하여 피연산자가 되는 변수의 타입 자체가 변경되지는 않고 다만 변수의 값을 변환된 값으로 반환될 뿐이다.

 

기본형 (primitive type) 에서 boolean을 제외한 나머지 타입들은 서로 형변환이 가능하다.

 

 

3. 정수형간의 형변환

 

정수형 안에서 값의 범위가 더 큰 타입에서 작은 타입으로 변환을 하는 경우에는 크기의 차이만큼 값이 잘려나가게 된다. 예를 들어서 4바이트의 int를 1바이트의 byte로 변환할때 1바이트 이상의 값들은 잘려나가게 된다. 그렇기 때문에 경우에 따라 값 손실이 발생할 수 있다.

 

반대로 작은 타입에서 큰 타입으로 가는 경우에는 저장공간 부족으로 인한 값 손실이 발생하지 않는다. 그리고 나머지 빈 공간은 0 또는 1로 채운다. 일반적으로는 0으로 채우지만 변환하려는 값이 음수인 경우에는 빈 공간을 1로 채운다.

 

 

4. 실수형간의 형변환

 

실수형에서도 정수형처럼 작은 타입에서 큰 타입으로 변환하는 경우 빈 공간을 0으로 채운다. float 타입을 double 타입으로 변환하는 경우 지수는 float의 기저인 127을 뺸 후 double 의 기저인 1023을 더해서 변환하고, 가수는 float의 가수 23자리를 채우고 남은 자리는 0으로 채운다. 이때 정수와 달리 실수의 값은 왼쪽에서부터 소수점에 가까운 자리이기 때문이기에 float의 23자리의 우측으로 0이 삽입된다.

 

반대로 double 타입에서 float 타입으로 변환하는 경우, 지수는 double의 기저인 1023을 뺀 후 float의 기저인 127을 더하고 가수는 double의 가수 52자리 중 왼쪽에서부터 12자리까지만 저장하게 된다.

한가지 주의할 점은 형변환시에 가수의 24번째 자리에서 올림이 발생할 수 있다는 것이다. double에서 float로 변환시에 가수의 24번째 자리의 값이 1이면 반올림이 발생하여 23번째 자리의 값이 1 증가한다.

그리고 float 타입의 범위를 넘는 값을 float로 형변환하는 경우 ±무한대, ±0의 결과를 얻게된다.

 

 

5. 정수형과 실수형 간의 형변환

 

앞에서 본 것과 같이 정수형과 실수형은 저장형식이 다르기 때문에 변환 과정 또한 좀 더 복잡하다.

 

- 정수형 -> 실수형 변환

 

정수는 소수점 이하의 값이 없기때문에 비교적으로 변환이 간단하다. 정수를 2진수로 바꾼 후 정규화를 거쳐 실수 형식으로 변환해주면 된다.

 

실수형은 정수형보다 훨씬 큰 저장범위를 가지고 있기 때문에 변환에 있어서 문제는 없다. 다만 실수형의 정밀도의 제한으로 인한 오차가 발생할 수 있다.

예를들어 int의 최대값은 약 20억으로 최대 10자리의 정밀도를 요구한다. 그러나 float의 경우 10진수로 7자리 정도의 정밀도만을 제공하기 때문에 int -> float으로 변환할 때 정밀도 차이에 의한 오차가 발생할 수 있다. 그렇기때문에 10진수로 8자리 이상의 값을 실수형으로 변환할 때는 double형으로 변환해야 오차가 발생하지 않는다.

 

- 실수형 -> 정수형 변환

 

실수형을 정수형으로 변환하면 소수점 이하의 값은 버려진다. 그래서 실수형을 정수형으로 형변환시에는 반올림이 발생하지 않는다.

만일 실수의 소수점을 버리고 남은 정수부가 정수형의 저장범위를 넘어가는 경우 오버플로우가 발생한다.

 

 

6. 자동 형변환

 

서로 다른 타입간의 연산을 위해서는 형변환으로 타입을 일치시켜주는 것이 원칙이지만 경우에 따라 편의상의 이유로 형변환을 생략할 수 있다. 자동 형변환의 경우 컴파일러가 생략된 형변환을 자동으로 추가한다.

 

예를 들어 실수형 변수에 정수형 리터럴을 입력하는 경우 또는 실수형과 정수형의 연산과 같은 상황에 자동 형변환이 적용된다. 이떄 두 타입중 더 표현범위가 넒은 타입으로 형변환을 진행하여 연산을 수행한다.

 

하지만 변수의 타입의 값의 범위보다 더 큰 값을 저장하려는 경우에는 형변환을 생략하면 에러가 발생한다.

 

- 자동 형변환의 규칙

 

컴파일러가 해주는 자동 형변환은 기존의 값을 최대한 보존할 수 있는 타입으로 자동 형변환을 수행한다. 그렇기 때문에 범위가 좁은 타입보다는 더 넓은 범위의 타입으로 변환되도록 한다.

 

byte (1) -> short, char (2) -> int (4) -> long (8) -> float (4) -> double (8)

 

보통은 메모리 사이즈가 더 큰 타입으로 변환되지만 정수형에서 실수형으로 변환되는 경우 실수형이 정수형보다 값을 표현하는 범위가 훨씬 넓기 때문에 정수형 -> 실수형으로 자동 형변환 된다.

 

char  short의 경우 같은 2바이트의 크기이지만 값을 표현하는 범위가 다르기 때문에 둘 간의 자동 형변환은 불가능하다.

 

 

[형변환 정리]

  1. boolean을 제외한 나머지 7개의 기본형은 서로 형변환이 가능하다.
  2. 기본형과 참조형은 서로 형변환할 수 없다.
  3. 서로 다른 타입의 변수간의 연산은 형변환을 하는 것이 원칙이지만, 값의 범위가 작은 타입에서 큰 타입으로의 형변환은 생략할 수 있다.
반응형

'프로그래밍언어 > JAVA' 카테고리의 다른 글

[JAVA] 연산자 - 단항 연산자  (0) 2021.08.10
[JAVA] 연산자 (Operator)  (0) 2021.08.10
[JAVA] 변수 타입 - 기본형 (primitive type)  (0) 2021.08.02
[JAVA] 진법 및 진법변환  (0) 2021.08.01
[JAVA] 변수의 타입  (0) 2021.07.29