💡 형변환?
변수 또는 상수의 타입을 다른 타입으로 변환하는 것을 말한다.
- 서로 다른 타입간의 연산을 수행해야 하는경우, 연산을 수행하기 전에 타입을 일치시켜야 한다.
- 서로 다른 타입 끼리의 값의 대입이나 연산은 불가능하기 때문이다. 이때 대입이나 연산이나 수행을 수행하기 전에 변수나 리터럴 타입을 다른 타입으로 변환하는 것을 형변환이라 한다,
💻 형변환 방법
형변환 하고자 하는 변수나 리터럴의 앞에 변환 하고자 하는 타입을 괄호()와 함께 붙여주면 된다.
- 괄호() : '캐스트연산자' or '형변환연산자'라고 한다.
- 피연산자에 저장된 값은 형변화 후에도 변화가 없다.
- 그저 값을 읽어 지정된 타입으로 변환하고 결과를 반환하기 때문이다.
- 기본형에서 boolean을 제외한 나머지 타입들은 서로 형변환이 가능하다.
- 기본형과 참조형 간의 형변환은 불가능하다.
🤔 정수형간의 형변환
크기가 큰 타입에서 작은 터입으로의 변환
크기가 작은 타입에서 큰 타입으로의 형변환
-
양수일 경우 나머지 공간을 0으로 채운다.
-
음수일 경우 1로 채운다.
-
값손실이 발생하지 않는다.
🤔 실수형 간의 형변환
크기가 큰 타입에서 작은 터입으로의 변환
- double => float
- 지수(E) : 기저(bias) 1023을 뺸 후 float의 기저인 127을 더한다.
- 가수(M) : 52자리 중 23자리만 저장하고 나머지는 버려진다. 52자리중 24번째 자리값이 1이면 반올림 발생, 23번째 자리가 1 증가한다.
크기가 작은 타입에서 큰타입으로의 형변환
- float => double
- 빈공간을 0으로 채운다.
- 지수(E) : 기저(bias)27을 뺸 후 double의 기저인 1023을더한다.
- 가수(M) : 23자리를 채운뒤, 남은 자리를 0으로 채운다.
float의 범위을 넘는 값을 float으로 변환
- ± 무한대 or ±0을 결과값으로 갖는다.
- 최대값보다 크면 ±무한대
- 최소값보다 작으면 ±0이다.
- 지수의 범위(-127~ 128)중 -127과 128은 숫자 아님(NaN)이나 양/음의 무한대(POSITIVE/NEGATIVE_INFINITY)와 같이 특별한 값의 표현을 위해 예약되어 있기 때문이다.
float과 double에 같은 값을 저장
- 저장 방식의 차이에 의해 같은 값을 저장 하더라도 실제로 저장되는 값이 다르다.(정밀도)
- 저장 방식의 차이에 의해 float의 가수는 23자리 까지만을 저장하고, double은 가수를 52자리 까지 저장하기 때문에 같은 소수라도 저장하는 과정에서 버려지는 부분이 발생한다.
- 저장할 때 값이 달라졌기 때문에 저장후에 형변환을 해도 값이 같아지지 않는다.
🤔 정수형과 실수형 간의 형변환
- 저장 방식이 완전히 다르기 때문에 복잡한 변환 과정을 거쳐야 한다.
정수형 => 실수형
- 정수를 2진수로 변환한다음 정규화를 거쳐 실수형의 저장 형식으로 저장된다.
- 소수정 이하의 값이 없으므로 비교적 변환이 간단하다.
- 실수형은 정수형보다 훨씬 큰 저장 범위를 갖기 떄문이다.
실수형의 정밀도 제한으로 인한 오차가 발생할 수 있다.
- int는 최대값이 약 20억으로 정밀도가 10자리인데 flaot은 약 7자리이다. 정밀도가 차이가 나기 때문에 큰값을 저장하면 오차가 발생할 수 있다.
- float의 가수 23 bit로 표현가능한 값일경우 오차없이 표현 가능하다.(정밀도가 7이다)
- double은 가수부가 52bit로 할당되어 있어 8자리 이상은 double형을 사용함으로 오차 발생을 해결할 수 있다. (정밀도가 15이다.)
실수형 => 정수형
- 실수형의 소수점 이하 값을 버려진다.
- 반올림이 발생하지 않는다.
- 정수형의 저장범위를 넘는 경우, 오버플로우가 발생한 결과를 얻는다,
🤔 형변환 안정장치
- 자바에서 제공하는 모든 기본 타입에 대한 최대값과 최소값의 상수를 사용하여 형변환의 값 손실을 방지할 수 있다.
- 상수를 활용하여 형변환 전 최소값과 최대값을 벗어나는지 검사를 하여 형변환을 할지 말지 선택하는 식으로 값 손실을 방지할 수 있다.
타입 | 최대값 상수 | 최소값 상수 |
---|
byte | Byte.MAX_VALUE | Byte.MIN_VALUE |
short | Short.MAX_VALUE | Short.MIN_VALUE |
short | Short.MAX_VALUE | Short.MIN_VALUE |
long | Long.MAX_VALUE | Long.MIN_VALUE |
float | Float.MAX_VALUE | Float.MIN_VALUE |
double | Double.MAX_VALUE | Double.MIN_VALUE |
int i = 128;
if( (i < Long.MIN_VALUE) || (i > Long.MAX_VALUE) ) {
System.out.println("Long타입의 범위를 넘어가는 값 입니다.");
} else {
long b = (long) i;
System.out.println(l);
}
💻 자동 형변환
- 서로 다른 타입간 대입/연신을 할때 형변환으로 타입을 일치 시키는 것이 원칙지만 경우에 따라 생략이 가능하다.
- 컴파일러가 생략된 형변환을 독자적으로 추가한다.
- 작은 크기를 가지는 타입이 큰 크기를 가지는 타입에 저장될 경우에만 발생한다.
float f = 1234
🤔 자동 형변환시 에러?
- 범위보다 더 큰 값을 저장할 때 형변환이 생략할 경우 에러가 발생한다.
byte b = 1000
- 명시적으로 형변환시 프로그래머의 의도한 것으로 간주하고 에러가 발생하지 않는다.
char ch = (char)1000
- 서로 다른 두 타입의 연산, 자동 형변환이 발생하여 타입을 일치 시킨뒤 연산을 수행하므로 에러가 발생하지 않는다.
int i = 3;
double d = 1.0 + i;
🤔 컴파일러는 어떤 기준으로 타입을 일치시킬까?
기존의 값을 최대한 보존할 수 있는 타입으로 타입으로 자동 형변환한다.
- 범위가 좁은 타입에서 넓은 타입으로 형변환 하는 경우 값 손실이 없기 때문이다.
- 왼쪽에서 오른쪽(=>)으로의 변환은 형변환 연산자를 사용하지 않아도 자동 형변환이 되지만, 반대 방향(<=)으로의 형변환은 형변환 연산자를 사용해야 한다.
- char에 short/byte를 형변환하여 저장할 수는 없다, 크기가 같거나 작지만 서포 표현 범위가 다르기 때문에(char은 음수를 표현할 수 없다) 값 손실이 발생할 수 있기 때문에 자동 형변환이 수행될 수 없다.
- 실수형은 정수형과 값을 표현하는 방식이 다르기 때문에 같은 크기라도 실수형이 더 큰 표현 범위를 갖기 때문에 오른쪽에 위치한다. float은 4byte고 long은 8byte지만 float은 부동소수점 방식으로 표현을 하기 때문에 실제 표현 범위가 더 크기 때문이다.
💻 산술 변환
연산 전에 피연산자 타입의 일치를 위해 자동 형변환 된는 것을 '산술 변환' 또는 '일반 산술 변환'이라한다.
🤔 산술 변환의 규칙
1. 두 피연산자의 타입을 같게 일치 시킨다.(큰 타입으로 일치시킨다.)
- 피연산자의 값손실을 최소화 하기 위함
2. 피연산자의 타입이 int보다 작은 타입이면 int로 변환된다.
- 자바는 피연산자를 4byte 단위로 저장하기 때문에, 정수 연산일 경우 int 타입이 기본이기 때문이다.
- 쉬프트 연산자와 증감 연산자에는 일어나지 않는다.
좋은 글이네요. 공유해주셔서 감사합니다.