Java - 연산과정의 형변환 및 다양한 연산자들

2020. 6. 13. 16:44Java

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
 
public class Ex {
 
    public static void main(String[] args) {
        /*
         * 산술 연산 시의 형변환
         * - 산술 연산 수행 전 피연산자의 타입을 일치시킨 후 연산을 진행함
         * 
         * 규칙1. int형보다 작은 타입끼리의 연산 시 int형으로 자동으로 변환 후 연산 
         *    ex) byte + byte = (int)byte + (int)byte = int
         *    ex2) byte + short = (int)byte + (int)short = int
         *    
         * 규칙2. int형 이상의 타입과 연산 시 피연산자 중 큰 타입으로 자동으로 변환 후 연산
         *    ex) char + int = (int)char + int = int
         *    ex2) byte + long = (long)byte + long = long
         *    ex3) long + float = (float)long + float = float
         */
        byte b1 = 10;
        byte b2 = 20;
//        byte b3 = b1 + b2; // 오류 발생! byte + byte = int
        // => b1 을 int형으로 변환, b2 를 int형으로 변환 후 덧셈 연산을 수행하기 때문에
        //    b1 + b2 의 결과가 byte 타입이 아닌 int 타입으로 계산됨
        //    따라서, 연산 결과를 byte 타입 변수 b3 에 저장하려면 명시적 형변환이 필요함
        
//        byte b3 = (byte)b1 + (byte)b2; // 오류 발생!
        // => 각 변수를 형변환 연산자를 사용하여 강제 형변환 시, 다시 자동으로 int형으로 변환됨
        //    즉, 연산에 참여하는 피연산자를 형변환하는 것이 아니라
        //    연산 수행 결과에 형변환 연산자를 적용해야 정상적인 형변환이 수행됨
        
        byte b3 = (byte)(b1 + b2); // 연산 결과가 int형이므로 결과값을 byte 로 변환
        System.out.println(b3);
        
        // -------------------------------
        char ch = 'A';
        System.out.println(ch);
        System.out.println(ch + 2); // char + int = int 이므로 C 가 아닌 67 출력됨
        System.out.println((char)(ch + 2)); // ch + 2 결과를 char 타입으로 형변환하여 'C' 출력됨
        
//        ch = ch + 2; // 오류 발생! 결과값이 int형이므로 char 타입에 저장 불가
        ch = (char)(ch + 2); // 연산 결과를 다시 char 타입으로 변환해야함
        System.out.println(ch);
        
        
        float f = 3.14f;
        long l = 100L;
//        long l2 = l + f; // long + float = float 이므로 long 타입으로 강제 형변환 필요
        long l2 = (long)(l + f);
        
        
        System.out.println(10 / 3); // int / int = int 이므로 정수 결과만 출력됨
        // => 만약, 10 / 3 연산을 실수 형태의 결과로 출력하고자 하는 경우
        //    두 피연산자 중 최소 하나의 피연산자를 실수형으로 변환해야함
        
        // 정수 리터럴을 실수형으로 변환하는 방법 2가지
        System.out.println(10 / 3f); // 1) 실수형 리터럴에 접미사 사용하거나 소수점 사용
        System.out.println(10 / (float)3); // 2) 형변환 연산자를 사용
        // => int / float = float 이므로 소수점 계산 가능
        
        System.out.println(10 / 3.0); // int / double = double 이므로 소수점 계산 가능
        
        System.out.println("----------------------");
        
        // int형보다 작은 타입의 리터럴 연산은 별도의 형변환이 발생하지 않는다.
        byte b = 10 + 20;
        // => 10 + 20 = int 형이지만, byte 타입이 충분히 담을 수 있는 값이므로 그대로 저장됨
        short s = 100 + 200;
        
        // 단, int보다 작은 타입 변수에 저장 가능한 범위를 벗어나면 오류 발생!
//        b = 100 + 28; // 오류 발생!
        // => byte 타입을 초과하므로 int -> byte 타입으로의 강제 형변환 필요
        
        // -------------------------------------------
        
        System.out.println('A' + 'B'); // char + char = int 이므로 131 출력
        System.out.println('1' + 2); // char + int = int 이므로 51 출력
        System.out.println('1' + '2'); // char + char = int 이므로 99 출력
        // => '1' + '2' 결과를 정수가 아닌 char 타입 문자로 출력할 경우
        System.out.println((char)('1' + '2'));
        
 
/*
         * 대입연산자(=)
         * - 우변의 데이터를 좌변의 변수에 대입(저장 = 할당)
         * - 모든 연산자 중 우선순위가 최하위
         * 
         * 복합(확장) 대입연산자(+=, -=, *=, /=, %=)
         * - 연산자 좌우변의 피연산자 2개를 각 산술 연산한 후 그 결과를 다시 좌변의 변수에 저장
         * - 복합 대입연산자를 사용하면 연산 과정에서의 자동 형변환이 일어나지 않는다!
         */
        
        int a = 10;
        
        int b = a; // 우변 a의 값을 좌변 b에 대입(할당 = 저장)
        System.out.println(b);
        
        // a + b 의 결과를 a 에 저장
        a += b; // a = a + b; 와 동일
        System.out.println(a);
        
        // a - b 의 결과를 a 에 저장
        a -= b; // a = a - b; 와 동일
        System.out.println(a);
 
        // a * b 의 결과를 a 에 저장
        a *= b; // a = a * b; 와 동일
        System.out.println(a);
 
        // a / b 의 결과를 a 에 저장
        a /= b; // a = a / b; 와 동일
        System.out.println(a);
 
        // a % b 의 결과를 a 에 저장
        a %= b; // a = a % b; 와 동일
        System.out.println(a);
                        
        System.out.println("---------------------");
        
        char ch = 'A';
        // ch 값을 2 만큼 증가시키기(ch + 2 결과를 다시 변수 ch 에 저장)
//        ch = ch + 2; // char + int = int + int = int 이므로 형변환 필수!
        
        // 형변환 연산자를 사용하여 명시적 형변환을 수행하는 방법
        ch = (char)(ch + 2);
        System.out.println(ch);
        
        // 복합 대입연산자를 사용하면 연산 과정에서의 자동 형변환이 일어나지 않는다!
        ch += 2// char 타입 변수 ch 값을 2만큼 증가시킴 => int형으로 변환되지 않음!
        System.out.println(ch);
        
/*
         * 비교(관계) 연산자(>, >=, <=, <, ==, !=)
         * - 두 피연산자의 대소관계를 비교하는 연산자
         * - 연산 결과로 true 또는 false 형태의 boolean 타입 결과가 리턴됨(= 전달됨)
         * - 주의! >= 등의 연산자 기호 순서를 바꿀 수 없다!
         */
        
        int a = 10, b = 3;
        
        System.out.println(a == b); // false 
        System.out.println(a != b); // true
        System.out.println(a > b); // true
        System.out.println(a >= b); // true
        System.out.println(a <= b); // false
        System.out.println(a < b); // false
        
        // 비교 연산 결과를 boolean 타입 변수에 저장도 가능하다!
        boolean result = a > b;
        System.out.println(result);
        
        System.out.println("---------------------");
        
        // char 타입의 비교 연산 시 유니코드(정수)로 변경하여 연산 수행
        System.out.println('A' > 'B'); // 65 > 66 = false
        
        // int형 이하의 연산 시 int형으로 자동 형변환 되는 것은 동일함
        System.out.println('A' == 65);
        
        // 두 피연산자 중 큰 타입으로 자동 형변환 되는 것도 동일함
        System.out.println(3 == 3.0); // int 타입 3 을 double 타입 3.0 으로 변환 후 연산 수행
        
        // ------------------------------------------------
        // 주의사항
        // 실수형의 경우 비교 연산에서도 정확도에 따른 문제점이 발생
        // => 주로 소수점 .1 에 대한 연산 시 근사치 표현 문제가 발생하게 됨
        System.out.println("0.1 과 0.1f 는 같은가? " + (0.1 == 0.1f)); // false
        System.out.println("0.5 과 0.5f 는 같은가? " + (0.5 == 0.5f)); // true
        
        double d1 = 0.1;
        float f1 = 0.1f;
        System.out.println(d1 == f1);
        
        // 해결 방법! 정수형으로 변환하여 연산을 수행하면 문제가 해결됨
        // => 실수의 모든 자릿수를 정수로 변환하기 위해 정수로 곱한 후 int형으로 형변환
        int i1 = (int)(d1 * 10);
        int i2 = (int)(f1 * 10);
        System.out.println(i1 == i2); // 0.1 == 0.1f 비교가 아닌 1 == 1 비교이므로 true
        
        
        // 동등비교연산자(==)의 경우 문자열 비교도 가능
        String s1 = "JAVA";
        String s2 = "java";
        String s3 = "java";
        
        System.out.println(s1 == s2); // "JAVA" 와 "java" 는 다른 문자(대소문자 구별)
        System.out.println(s3 == s2); // "java" 와 "java" 는 같은 문자
        
 
/*
         * 증감연산자(++, --)
         * - 변수의 값을 1만큼 증가시키거나 감소시키는 연산자
         * - 변수의 앞쪽(좌측)에 붙을 경우 전위연산자(선행연산자)라고 하며,
         *   변수의 뒷쪽(우측)에 붙을 경우 후위연산자(후행연산자)라고 함
         *   => 다른 연산자와 함께 사용될 경우 위치에 따라 연산 순서가 달라지므로 주의!
         *   1) 전위연산자(선행연산자) : 다른 연산보다 먼저 변수 값을 증감시킨 후 다른 연산 수행
         *   2) 후위연산자(후행연산자) : 다른 연산을 먼저 수행한 후, 변수 값을 증감시킴
         * - 대입연산자를 조합하여 1 증가시키는 연산과 결과적으로 수치 변화는 동일하지만
         *   대입연산자와 산술연산자를 사용하는 연산보다 연산 속도가 빠름
         * - 복합 대입연산자와 마찬가지로 연산 과정에서 자동 형변환이 발생하지 않음
         */
        int i = 5;
        
        i++// 현재 i값을 1 증가시킴(5 -> 6)
        System.out.println(i); // i값 출력(6)
        
        ++i; // 현재 i값을 1 증가시킴(6 -> 7)
        System.out.println(i); // i값 출력(7)
        
        // 증감연산자가 다른 연산자와 함께 사용될 경우 위치에 따라 연산 순서가 달라짐
        int j = ++i; // 선행연산자이므로 i값을 먼저 1 증가시킨 후, 증가된 값을 j 에 전달
        // i 값이 7 -> 8 로 증가된 후 j에 8이 전달됨(i = 8, j = 8)
        
        System.out.println("i = " + i + ", j = " + j);
        
        System.out.println(j++);
        // => 후행연산자이므로 j값을 먼저 출력문에 사용한 후, j값을 1 증가시킴
        //    j가 8일 때 출력된 후, j 값이 8 -> 9 로 증가됨
        
        System.out.println(--j);
        // => 선행연산자이므로 j값을 먼저 1 감소시킨 후, 출력문에 j값을 사용
        //    j 값이 9 -> 8 로 감소된 후, j 값 8이 출력됨
        
        System.out.println("============================");
        
        int x = 5;
        int y = ++x; // 선행연산자이므로, x값을 먼저 1 증가시킨 후, x값을 y에 전달
        System.out.println(x + ", " + y); // x = 6, y = 6
        
        int x2 = 5;
        int y2 = x2++// 후행연산자이므로, x2값을 먼저 y2에 전달한 후, x2값을 1 증가시킴 
        System.out.println(x2 + ", " + y2); // x2 = 6, y2 = 5
        
        System.out.println("===========================");
        
        char ch = 'A';
        
        // 1. 산술연산자와 대입연산자를 조합하여 ch 값을 1 증가시키는 방법
        ch = (char)(ch + 1); // char + int = int 이므로 형변환 연산자 필요
        System.out.println(ch);
        
        // 2. 복합 대입연산자를 사용하여 ch 값을 1 증가시키는 방법
        ch += 1// 형변환 필요없음
        System.out.println(ch);
        
        // 3. 증감연산자를 사용하여 ch 값을 1 증가시키는 방법
        ch++// 형변환 필요없음
        System.out.println(ch);
        
    }
 
}
 
 
 
cs

저번 시간에 이어서 형 변환에 대해 조금 더 배우고 다양한 연산자들에 대해서 배워보았다. 저번엔 간단한 입력 과정에서의 형 변환이었다면 이번엔 연산과정에서 일어나는 자동적인 형 변환들과 강제로 결괏값을 형 변환시킬 수 있는 문법을 배워보았다. 간단해 보이지만 헷갈려서 꼬여 버릴 수 있다고 생각된다. 조금 더 신경 써서 여러 번 보아서 자동으로 생각의 흐름이 따라갈 수 있게 익숙해져야 할 거 같다. 그리고 연산자들에 대해 여러 가지 형식을 배워 보았는데 헷갈릴 수 있다고 생각이 드는 것이 제일 간단해 보이는 증감 연산자 ++x, x++이라고 생각이 들었다. 출력 후 증감이 이루어지는지 증감이 이루어지고 출력이 되는지 가 연산과정을 짤 때 헷갈리게 되는 부분이 있어 좀 버벅되게 되었다. 확실하게 짚고 넘어가야 하는 부분이라고 생각이 들었고 좀 더 머릿속에 박아 넣어야겠다.