Java에서 형변환 이라는 개념이 있다. 그리고 자바의 형변환에는 형변환 순서라는 것이 존재한다
이 순서는 기본적으로 작은 타입에서 큰 타입으로 형변환을 하는 경우를 의미한다. 산술변환에 대해 보기 앞서, 한가지 의문점이 들만한 점이있다. 바로 8Byte long
타입이 왜 더 작은 4Byte float
으로 형변환된다는 것이다.
기초적인 내용으로 접근해 보자. Java 역시 Primitive Data Type이 존재하고, 실수형으로는 float와 double이 존재한다. 그리고 이 float와 double은 부동소수점
방식으로 실수를 표현한다.(IEEE 754,참고) float와 double의 표현 범위는 아래와 같다.(양수범위만 의미하며, 음수범위는 해당 범위에 -
를 붙이면 됨)
Type | 범위 | 정밀도 | 크기 |
---|---|---|---|
float | 1.4 x 10^-45 ~ 3.4 x 10^28 | 7자리 | 32비트, 4바이트 |
double | 4.9 x 10^-324 ~ 1.8 x 10^308 | 15자리 | 64비트, 8바이트 |
float와 int의 저장 방식에는 차이가 존재한다.
여기서 'S'
는 부호비트를 의미한다. int타입 같은 경우 부호비트와 값 두 파트로 이루어져 있다면, float같은 경우에는, 부호(S), 지수(E), 가수(M) 세 부분으로 이루어져 있다. 이는 아래와 같은 형태로 저장하기 때문이다.
(+ or -) M x 2^E
위 표에서 정밀도
라는 것은 a x 10^n(1<= a < 10)
의 형태로 표현된 7자리의 10진수를 오차없이 저장할 수 있다라는 의미이다. 7자리 이상의 정밀도가 필요하다면, 변수 타입을 double로 변경해야하며, 실수형을 저장할 때 double로 하는 이유는 값의 범위
의 이유가 아닌 높은 정밀도
라는 이유에서이다.(단 메모리 크기가 2배가 나므로, 공간복잡도를 고려했을때는 float를 우선순위로 둔다.) 결론적으로 7자리 이상의 int가 float로 형변환 후 다시 int로 형변환 하면, 원래의 값으로 되돌아오는것을 보장하지 못한다는 것이다.
이항 연산자는 두 피연산자의 타입이 일치해야 한다. 그렇기 때문에 자바는 연산을 하기 전에 피연산자간에 타입이 다른 경우, 자동으로 형변환을 하여 타입을 일치시킨다. 그리고 형변환은 위에서 보았던 형변환 순서를 고려하여 형변환이 되게 된다. 산술 변환 규칙에는 두개의 규칙이 있다.
이렇게 하는 이유는 부동소수점을 봤을때처럼, 값 손실 최소화
와 Overflow 방지를 위해서
가 대표적인 이유이다.
감사합니다.