5. 형변환
5.1 형변환(캐스팅, casting)이란?
- 형변환 : 변수 또는 상수의 타입을 다른 타입으로 변환하는 것
> int타입의 값과 float타입의 값을 더하는 경우, 먼저 두 값을 같은 타입으로 즉, 둘 다 float 타입으로 변환한 후에 더함
5.2 형변환 방법
- 형변환하고자 하는 변수나 리터럴의 앞에 변환하고자 하는 타입의 괄호를 함꼐 붙여줌
> (타입)피연산자
1
2
3
4
5
6
7
|
double d = 85.4;
int score = (int)d; // double 타입의 변수 d를 int타입으로 형변환
int score = (int)85.4; // 변수 d의 값을 읽어 와서 형변환한다.
int score = 85; // 형변환의 결과인 85를 변수 score에 저장
|
cs |
>> 피연산자인 변수 d의 값은 형변환 후에도 아무런 변화가 없다.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public class CastingEx1_ {
public static void main(String[] args) {
double d = 85.4;
int score = (int)d;
System.out.println("score="+score);
System.out.println("d+"+d);
}
}
|
cs |
score=85
d+85.4 → 형변환 후에도 피연산자에는 아무런 변화가 없음
* 기본형간의 형변환
- int → char
> 수식 : (char) 65
> 결과 : 'A'
- char → int
> 수식 : (int) 'A'
> 결과 : 65
- float → int (> 소수점 이하 값은 버림으로 처리)
> 수식 : (int) 1.6f
> 결과 : 1
- int → float
> 수식 : (float) 10
> 결과 : 10.0f
5.3 정수형간의 형변환
- 큰 타입에서 작은 타입으로의 변환(ex. int타입 → byte타입)하는 경우, '값손실(loss of data)'이 발생할 수 있음
- 작은 타입에서 큰 타입으로의 변환(ex. byte타입 → int타입)하는 경우, 값손실 발생 x, 나머지 빈 공간은 0이나 1로 채움
> 남은 빈 공간은 보통 0으로 채우지만, 변환하려는 값이 음수인 경우에는 빈 공간을 1로 채움(부호를 유지하기 위해)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
public class CastingEx2 {
public static void main(String[] args) {
int i = 10;
byte b = (byte)i;
System.out.printf("[int -> byte] i=%d -> b=%d%n", i, b);
i = 300;
b = (byte)i; // 값손실 있음
System.out.printf("[int -> byte] i=%d -> b=%d%n", i, b);
b = 10;
i = (int)b;
System.out.printf("[byte -> int] b=%d -> i=%d%n", b, i);
b = -2;
i = (int)b;
System.out.printf("[byte -> int] b=%d -> i=%d%n", b, i);
System.out.println("i="+Integer.toBinaryString(i));
}
}
|
cs |
[int -> byte] i=10 -> b=10
[int -> byte] i=300 -> b=44
[byte -> int] b=10 -> i=10
[byte -> int] b=-2 -> i=-2
i=11111111111111111111111111111110
5.4 실수형 간의 형변환
- 실수형에서도 정수형처럼 작은 타입에서 큰 타입으로 변환하는 경우, 빈 공간을 0으로 채움
- float 타입→ double 타입 변환
> 지수(E) : float의 기저인 127을 뺀 후 double의 기저인 1023을 더해서 변환
> 가수(M) : float의 가수 23자리를 채우고 남은 자리를 0으로 채움
- double 타입→ float 타입 변환
> 지수(E) : double의 기저인 1023을 뺀 후 float의 기저인 127을 더함
> 가수(M) : double의 가수 52자리 중 23자리만 저장되고 나머지는 버려짐
>> 형변환할 때, 가수의 24번째 자리에서 반올림이 발생할 수 있음
(24번째 자리의 값이 1이면, 반올림이 발생하여 23번째 자리의 값이 1 증가)
>> float 타입의 범위를 넘는 값을 float로 형변환하는 경우는 '+-무한대' 또는 '+-0'을 결과로 얻음
1
2
3
4
5
|
double d = 1.0e100; // float의 최대값보다 큰 값을 d에 저장(1.0x10^100)
float f = (float)d; // d의 값을 float으로 형변환해서 f에 저장. f는 무한대가 된다.
double d = 1.0e-50; // float의 최소값보다 작은 값을 d에 저장(1.0x10^-50)
float f = (float)d; // f의 값은 0이 된다.
|
cs |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public class CastingEx3_ {
public static void main(String[] args) {
float f = 9.1234567f;
double d = 9.1234567;
double d2 = (double)f;
System.out.printf("f =%20.18f\n", f);
System.out.printf("d =%20.18f\n", d);
System.out.printf("d2 =%20.18f\n", d2);
}
}
|
cs |
f =9.123456954956055000
d =9.123456700000000000
d2 =9.123456954956055000
5.5 정수형과 실수형 간의 형변환
* 정수형을 실수형으로 변환
: 정수를 2진수로 변환한 다음 정규화를 거쳐 실수의 저장형식으로 저장
- 실수형의 정밀도 제한으로 인한 오차가 발생할 수 있음
> 따라서, 10진수로 8자리 이상의 값을 실수형으로 변환할 때는 float가 아닌 double로 형변환을 해야 함
* 실수형을 정수형으로 변환
: 정수형의 표현 형식으로 소수점 이하의 값은 표현할 수 없기 때문에, 실수형의 소수점이하 값을 버려짐
> 그래서 실수형을 정수형으로 형변환할 때는 반올림이 발생하지 않음
>> 만약 실수의 소수점을 버리고 남은 정수가 정수형의 저장범위를 넘는 경우에는 정수의 오버플로우가 발생
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
public class CastingEx4_ {
public static void main(String[] args) {
int i = 91234567; // 8자리의 10진수
float f = (float)i; // int를 float로 형변환
int i2 = (int)f; // float를 다시 int로 형변환
double d = (double)i; // int를 다시 double로 형변환
int i3 = (int)d; // double을 다시 int로 형변환
float f2 = 1.666f;
int i4 = (int)f2;
System.out.printf("i=%d\n", i);
System.out.printf("f=%f i2=%d\n", f, i2);
System.out.printf("d=%f i3=%d\n", d, i3);
System.out.printf("(int)%f=%d\n", f2, i4);
}
}
|
cs |
i=91234567
f=91234568.000000 i2=91234568
d=91234567.000000 i3=91234567
(int)1.666000=1
5.6 자동 형변환
- 서로 다른 타입간의 대입이나 연산을 할 때, 편의상 형변환이 생략된 경우에는 컴파일러가 형변환을 자동적으로 추가함
1
2
3
|
float f = 1234; // 형변환의 생략. float f = (float)1234;
|
cs |
- 변수가 저장할 수 있는 값의 범위보다 더 큰 값을 저장하려는 경우에 형변환을 생략하면, 에러가 발생
1
2
3
|
byte b = 1000; // 에러. byte의 범위(-128~127)를 넘는 값을 저장.
|
cs |
- 에러 메시지 : incompatible types: possible lossy conversion from int to byte
> 큰 타입에서 작은 타입으로의 형변환은 값 손실이 발생할 수 있다는 뜻
- 명시적으로 형변환 해줬을 경우, 형변환이 의도적인 것으로 간주하고 컴파일러는 에러를 발생 시키지 않음
1
|
char ch = (char)1000; // 명시적 형변환. 에러가 발생하지 않음
|
cs |
* 산술 변환 : 연산과정에서 자동적으로 발생하는 형변환
- 서로 다른 두 타입의 연산에서는 먼저 타입을 일치시킨 다음에 연산을 수행해야 하므로, 형변환이 자동으로 이루어짐
1
2
|
int i = 3;
double d = 1.0 + i; // double d = 1.0 + (double)i;에서 형변환이 생략됨
|
cs |
- 서로 다른 두 타입간의 덧셈에서는 두 타입 중 표현범위가 더 넓은 타입으로 형변환하여 일치시킨 뒤 연산을 수행
> 값손실의 위험이 더 적어서 올바른 결과를 얻을 수 있음
1
2
3
4
5
|
double d = 1.0 + i;
→ double d = 1.0 + (double)i;
→ double d = 1.0 + (double)3; // 3을 double타입으로 형변환하면 3.0이 된다.
→ double d = 1.0 + 3.0; // double과 double의 덧셈결과 타입은 double.
→ double d = 4.0; // double + double = double
|
cs |
* 자동 형변환의 규칙
- 컴파일러는 기존의 값을 최대한 보존할 수 있는 타입으로 자동 형변환한다.
: 표현범위가 좁은 타입에서 넓은 타입으로 형변환하는 경우에는 값 손실이 없으므로,
두 타입 중에서 표현범위가 더 넓은 쪽으로 형변환 된다.
'Java' 카테고리의 다른 글
[Java] 환경변수 설정 / Hello World / 변수(데이터)의 종류와 크기(byte, short, int, long, float, double, char, boolean) (0) | 2023.03.02 |
---|---|
[자바의 정석] #CH.3 연산자 operator - 3.1 연산자와 피연산자 / 3.2 단항 연산자 (0) | 2023.02.01 |
[자바의 정석] #CH.2 변수 Variable - 2.4 기본형(primitive type) (0) | 2023.01.18 |
[자바의 정석] #CH.2 변수 Variable - 2.3 진법 (0) | 2023.01.17 |
[자바의 정석] #CH.2 변수 Variable - 2.2 변수의 타입 (0) | 2023.01.16 |