1. 정수형과 실수형 간의 형 변환
정수형과 실수형은 저장 형식이 완전 다르기 때문에 정수형 간의 변환처럼 간단히 값을 변환할 수 없다.
int : 1+31=32 (4byte) | |||
S(1) | 31bit | ||
float : 1+8+23=32 (4byte) | |||
S(1) | E(8) | M(23) |
정수형을 실수형으로 변환
정수는 소수점 이하의 값이 없으므로 비교적 변환이 간단하다. 2진수로 변환한 다음 정규화를 거쳐 실수의 저장 형식으로 저장한다.
정규화 링크 추가
실수형은 정수형보다 훨씬 큰 저장 범위를 갖기 때문에, 정수형을 실수형으로 변환하는 것은 별 무리가 없다. 단, 실수형의 정밀도의 제한으로 인한 오차가 발생할 수 있다.
91234567 ─ (float) ─> 91234568.0 ─ (int) ─> 91234568
91234567 ─ (double) ─> 91234567.0 ─ (int) ─> 91234567
* float는 정밀도가 약 7자리이므로 8자리의 정수를 저장할 때 오차가 발생한다.
실수형을 정수형으로 변환
실수형을 정수형으로 변환하면, 실수형의 소수점 이하 값은 버려진다. 실수형을 정수형으로 형 변환할 때 반올림은 발생하지 않는다.
1.666 ─ (int) ─> 1
* 실수의 소수점을 버리고 남은 정수가 정수형의 저장 범위를 넘는 경우, 정수의 오버플로우가 발생한다.
2. 자동 형 변환
서로 다른 타입 간의 대입이나 연산을 할 때, 형 변환으로 타입을 일치시키는 것이 원칙이지만 경우에 따라 형 변환을 생략할 수 있다. 이를 '묵시적 형 변환'이라고 한다.
float f = 1234; // 묵시적 형변환. float f = (float)1234;와 같음
위의 문장에서 우변은 int 타입의 상수이나, float 타입으로 저장하는데 아무런 문제가 없기에 형 변환을 생략하였다.
byte b = 1000; // 에러. byte의 범위(-128~127)를 넘는 값임
그러나 위와 같이 변수가 저장할 수 있는 값의 범위보다 더 큰 값을 저장하려는 경우에 형 변환을 생략하면 에러가 발생한다. 이런 경우 앞서 언급했던 '(타입)피연산자'(=명시적 형 변환)로 형 변환을 해줘야 한다.
char ch = (char)1000; // 명시적 형변환. 에러가 발생하지 않는다.
또 다른 예로, 서로 다른 두 타입의 연산과정에서 형 변환이 자동적으로 이루어진다. 형 변환은 두 타입 중 표현 범위가 더 넓은 타입으로 진행한다.
int i = 3;
double d = 1.0 + i; // 형변환이 생략됨. double d = 1.0 + (double)i;
* 연산과정에서 자동적으로 발생하는 형 변환을 '산술 변환'이라고 한다.
자동 형 변환의 규칙
byte(1byte) → short, char(2byte) → int(4byte) → long(8byte) → float(4byte) → double(8byte)
* 피연산자의 타입이 int보다 작은 타입이면 int로 변환한다.
1. boolean을 제외한 7개의 기본형은 서로 형 변환이 가능하다.
2. 기본형과 참조형은 서로 형 변환할 수 없다.
3. 서로 다른 타입의 변수 간의 연산은 형 변환을 하는 것이 원칙이지만,
값의 범위가 작은 타입에서 큰 타입으로의 형 변환은 생략할 수 있다.
참고문헌 : 남궁성(2016), Java의 정석, 도우출판