안녕하세요, 여행벌입니다.
오늘은 자바 연산자 중 이항 연산자들에 대해서 다뤄보겠습니다.
자바 연산자 종류
연산기호 |
결합 방향 |
우선순위 ( 낮을수록 높음 ) |
[ ], ( ), . |
→ |
1 |
expr++, expr-- |
← |
2 |
++expr, --expr, +expr, -expr, ~, !, (type), new |
← |
3 |
*, /, % |
→ |
4 |
+, - |
→ |
5 |
<<, >>, >>> |
→ |
6 |
<, >, <=, >=, instanceof |
→ |
7 |
==, != |
→ |
8 |
& |
→ |
9 |
^ |
→ |
10 |
| |
→ |
11 |
&& |
→ |
12 |
|| |
→ |
13 |
? expr : expr |
← |
14 |
=, +=, -=, *=, /=, %=, ^=, |=, <<=, >>=, >>>= |
← |
15 |
이항 연산자
피연산자가 둘인 연산자를 가리켜 '이항 연산자(binray operator)' 라 합니다. 피연산자는 데이터 그 자체를 대표함과 동시에 조작, 연산에 사용할 데이터를 지정하는 컴퓨터 명령의 일부입니다.
대입 연산자와 산술 연산자 : =, +, -, *, /, %
연산자 | 연산자의 기능 | 결합 방향 |
= |
연산자 오른쪽에 있는 값을 연산자 왼쪽에 있는 변수에 대입. a = 5; |
← |
+ |
두 연산자의 값을 더한다. a = 4 + 3; |
→ |
- |
왼쪽의 피연산자 값에서 오른쪽의 피연산자 값을 뺀다. a = 4 - 3; |
→ |
* |
두 피연산자의 값을 곱한다. a = 4 * 3;
|
→ |
/ |
왼쪽의 피연산자 값을 오른쪽의 피연산자 값으로 나눈 몫을 반환한다. a = 4 / 3; |
→ |
% |
왼쪽의 피연산자 값을 오른쪽의 피연산자 값으로 나눴을 때 얻게 되는 나머지를 반환한다. a = 4 % 3; |
→ |
복합 대입 연산자 : +=, -=, *=, /=, %=, &=, ^=, <<=, >>=, >>>=
연산자 | 연산자의 기능 |
+= | a += b 는 a = a + b; 와 같습니다 |
-= | a -= b 는 a = a - b; 와 같습니다. |
*= | a *= b 는 a = a * b; 와 같습니다. |
/= | a /= b 는 a = a / b; 와 같습니다. |
%= | a %= b 는 a = a % b; 와 같습니다. |
&= | a &= b 는 a = a & b; 와 같습니다. |
^= | a ^= b 는 a = a ^ b; 와 같습니다. |
<<= | a <<<= b 는 a = a << b; 와 같습니다. |
>>= | a >>= b 는 a = a >> b; 와 같습니다. |
>>>= | a >>>= b 는 a = a >>> b; 와 같습니다. |
관계 연산자 : <, >, <=, >=, ==, !=
관계 연산자는 두 개의 피연산자 사이에서 크기 및 동등 관계를 따져주는 이항 연산자로 결과에 따라서 true 또는 false를 반환합니다.
연산자 | 연산자의 기능 | 결합 방향 |
< |
a < b a 가 b 보다 작은가? |
→ |
> |
a > b a 가 b 보다 큰가? |
→ |
<= |
a <= b a 가 b 보다 작거나 같은가 |
→ |
>= |
a >= b a 가 b 보다 크거나 같은가 |
→ |
== |
a == b a 가 b 랑 같은가? |
→ |
!= |
a != b a 가 b랑 다른가? |
→ |
논리 연산자 : &&, ||, !
연산자 | 연산자의 기능 | 결합 방향 |
&& |
A && B A와 B 모두가 true이면 true, 아니면 false ( 논리 AND 와 동일 ) |
→ |
|| |
A || B A와 B 모두가 false이면 false, 아니면 true ( 논리 OR 과 동일 ) |
→ |
! |
!A A가 true이면 false, false이면 true 반환 ( 논리 NOT ) |
→ |
예시 1)
package Hello;
public class HelloWorld {
public static void main(String args[]) {
int num1 = 0;
int num2 = 0;
boolean result;
result = ((num1 += 10) < 0) && ((num2 += 10) > 0);
System.out.println(result);
System.out.println(num1);
System.out.println(num2);
}
}
위의 출력 결과는 어떻게 될까요?
false
10
0
num1은 10이지만, num2는 0인 것을 확인할 수 있습니다. 그 이유는 && 연산자 때문입니다. ( (num1 += 10) < 0 ) 이 먼저 수행되는데, num1 += 10을 하면 num1은 10이 되므로 0보다 작지 않습니다. 따라서 ( (num1 += 10) < 0 ) 은 false가 됩니다. 이때, && 연산자는 false가 하나라도 존재하면 어차피 false 값을 같습니다. 따라서 ( (num2 += 10) > 0) 연산을 진행하지 않고 result 에는 false가 저장됩니다.
예시 2)
package Hello;
public class HelloWorld {
public static void main(String args[]) {
int a = 5; // 코드 1번
System.out.println(a++); // 코드 2번
System.out.println(a); // 코드 3번
System.out.println((a++ + 5) * 3); // 코드 4번
a = (a++ + 5) * 3; // 코드 5번
System.out.println(a); // 코드 6번
}
}
위의 코드는 어떤 값들을 출력할까요? 정답은 아래와 같습니다!
5
6
33
36
코드 1번에서 a 에 5를 할당합니다.
코드 2번에서는 a를 출력한 후, ++ 연산이 진행되므로 '5'를 출력하지만 a의 값은 6이 됩니다.
코드 3번은 코드 2번에 의해 '6' 을 출력하게 됩니다.
코드 4번에는 ( ) , ++, +, * 4가지 연산이 등장합니다. 우선순위는 ( ), ++, *, + 순으로 괄호 안에 식을 먼저 진행해야 됩니다. 따라서 ++ 과 + 연산이 진행되는데 이때, ++ 연산은 명령을 마무리 한 후에 a의 값을 올려주므로 (6 + 5) 가 진행됩니다. 그 후 * 3을 해서 33이라는 값이 만들어지고 a는 1 증가해서 7이 됩니다.
코드 5번은 ( ), ++, +, * , = 5가지 연산이 등장합니다. 우선순위는 ( ), ++, *, +, = 순으로 코드 4번과 마찬가지로 괄호 안에 식을 먼저 진행해야됩니다. 따라서 (7 + 5) 가 먼저 계산되고, 12 * 3이 계산되고 ++ 연산에 의해 a는 1 증가해서 8이 됩니다. 하지만 = 연산에 의해 계산된 36이란 값이 a에 저장되므로 a는 결국 36이 저장됩니다.
예시 3)
package Hello;
public class HelloWorld {
public static void main(String args[]) {
int a = 1; // 코드1
a = ~a; // 코드2
System.out.println(a); // 코드3
}
}
위의 예시는 어떤 값을 출력할까요?
-2
정답은 '-2' 입니다.
컴퓨터는 모든 숫자를 2진수로 저장합니다. 우리는 앞의 포스팅에서 int 는 4바이트로 이루어져 있다고 배웠습니다. 따라서, a에 1을 할당하면 다음과 같이 컴퓨터에는 저장됩니다.
a = 0000 0000 0000 0000 0000 0000 0000 0001 (2)
~ 연산은 쉽게 말하면 2진수로 저장된 a의 비트들을 반대로 바꿔주는 연산입니다. 즉, 코드2에 의해 a는 다음과 같이 바뀝니다.
a = 1111 1111 1111 1111 1111 1111 1111 1110 (2)
컴퓨터가 정수는 저장하는 방법인 2의 보수법에 의하면 위의 2진수 코드는 '-2' 를 의미합니다. 따라서 -2가 출력됩니다.
예시 4) 비트 연산자
<< 연산자는 비트 값들을 왼쪽으로 이동시킨 후에 오른쪽의 빈 공간에는 모두 0으로 채운다.
>> 연산자는 비트 값들을 오른쪽으로 이동시킨 후에 왼쪽의 빈 공간에 양수라면 0으로, 음수라면 1로 채워줍니다.
>>> 연산자는 비트 값들을 오른쪽으로 이동시킨 후에 부호와 상관없이 0으로 채워줍니다.
package Hello;
public class HelloWorld {
public static void main(String args[]) {
int a = 1; // 코드1
a = a << 5; // 코드2
System.out.println(a);
a = a >> 3; // 코드3
System.out.println(a);
int b = -2147483648; // 코드4
b = b >> 1; // 코드5
System.out.println(b);
int c = -2147483648; // 코드6
c = c >>> 1; // 코드7
System.out.println(c);
}
}
위의 예시는 어떤 값들을 출력할까요?
32
4
-1073741824
1073741824
코드1에서 a에 1을 할당하므로 a = 0000 0000 0000 0000 0000 0000 0000 0001 (2) 가 됩니다.
코드2에 의해 a는 왼쪽으로 5칸씩 비트가 이동하게 되고, 오른쪽의 파란 부분에는 0이 채워지고 위의 노란 부분에 해당하는 비트들은 사라지게 됩니다.
a = 0000 0000 0000 0000 0000 0000 0010 0000 (2)
따라서, 현재 a는 10진법으로 32를 나타냅니다.
코드3에 의해 a는 오른쪽으로 3칸씩 비트가 이동하게 되고, 양수이므로 왼쪽의 빨간 부분에 0이 채워지게 됩니다.
a = 0000 0000 0000 0000 0000 0000 0000 0100 (2)
따라서, 현재 a는 10진법으로 4를 나타냅니다.
코드4에서 b에 -2147483648 을 할당하므로 b = 1000 0000 0000 0000 0000 0000 0000 0000(2) 가 됩니다.
코드5에서 >> 연산은 음수 값은 왼쪽의 비는 부분을 1로 채우므로 b = 1100 0000 0000 0000 0000 0000 0000 0000(2) 가 되고, 10진수로 표현하면 -1073741824 가 됩니다.
코드6에서 c = 1000 0000 0000 0000 0000 0000 0000 0000(2) 가 됩니다.
코드7에서 >>> 연산은 부호에 상관 없이 왼쪽의 비는 부분을 0으로 채우므로 c = 0100 0000 0000 0000 0000 0000 0000 0000(2) 가 됩니다. 부호를 나타내는 맨 앞 코드가 0이 되어서 c는 양수가 되고 10진수로 표현하면 1073741824가 됩니다.
비트 연산자는 따로 다른 포스팅에서 자세히 다뤄보겠습니다.
'Computer Language > JAVA' 카테고리의 다른 글
[JAVA] #7 자바 비트 연산자 - travelbeeee (0) | 2020.03.19 |
---|---|
[JAVA] #6 자바 단항 연산자 - travelbeeee (0) | 2020.03.17 |
[JAVA] #4 자바 형 변환 - travelbeeee (0) | 2020.03.13 |
[JAVA] #3 자바 리터럴(Literals), 리터럴 상수 - travelbeeee (0) | 2020.03.13 |
[JAVA] #2 자바 상수 ( final ) - travelbeeee (0) | 2020.03.13 |