> For the complete documentation index, see [llms.txt](https://nbcamp.gitbook.io/java-handbook/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://nbcamp.gitbook.io/java-handbook/part-02./undefined-4.md).

# 논리 연산자와 비트 연산자

## 논리 연산자

| 논리 연산자 |                                      설명                                     |
| :----: | :-------------------------------------------------------------------------: |
|   &&   |       논리식이 모두 참이면 참을 반환함. (논리 <mark style="color:blue;">AND</mark> 연산)      |
|  \|\|  |     논리식 중에서 하나라도 참이면 참을 반환함. (논리 <mark style="color:blue;">OR</mark> 연산)    |
|    !   | 논리식의 결과가 참이면 거짓을, 거짓이면 참을 반환함. (논리 <mark style="color:blue;">NOT</mark> 연산) |

|   A   |   B   | A && B | A \|\| B |   !A  |
| :---: | :---: | :----: | :------: | :---: |
|  true |  true |  true  |   true   | false |
|  true | false |  false |   true   | false |
| false |  true |  false |   true   |  true |
| false | false |  false |   false  |  true |

* 아래 예제코드로 학습해 보겠습니다.

{% code lineNumbers="true" %}

```java
class Operator7_1 {
    public static void main(String[] args) {
        boolean result1, result2, result3, result4, reusult5, result6;

        char ch1 = 'a', ch2 = 'B';  // 'a' : 97 , 'A' : 65, 'B' : 66, 'C' : 67

        result1 = ch1 > 'A' && ch2 < 'C';
        result2 = ch1 == 'A' && ch2 < 'C';

        result3 = ch1 > 'A' || ch2 < 'C';
        result4 = ch1 < 'A' || ch2 > 'C';

        System.out.println("&& 연산자에 의한 결과 result1 = " + result1); // true
        System.out.println("&& 연산자에 의한 결과 result2 = " + result2); // false

        System.out.println("|| 연산자에 의한 결과 result3 = " + result3); // true
        System.out.println("|| 연산자에 의한 결과 result4 = " + result4); // false

        System.out.println("! 연산자에 의한 결과 result4 = " + !result4); // true

        System.out.println();

        int num = 10;
        // num 은 2의 배수 그리고 3의 배수이다.
        reusult5 = num % 2 == 0 && num % 3 == 0;
        System.out.println("num 은 2의 배수 그리고 3의 배수 = " + reusult5); // false

        // num 은 2의 배수 또는 3의 배수이다.
        result6 = num % 2 == 0 || num % 3 == 0;
        System.out.println("num 은 2의 배수 또는 3의 배수 = " + result6); // true
    }
}
```

{% endcode %}

## 비트 연산자

| 비트 연산자 |                           설명                          |
| :----: | :---------------------------------------------------: |
|    &   |          대응되는 비트가 모두 1이면 1을 반환함. (비트 AND 연산)          |
|   \|   |        대응되는 비트 중에서 하나라도 1이면 1을 반환함. (비트 OR 연산)        |
|    ^   |          대응되는 비트가 서로 다르면 1을 반환함. (비트 XOR 연산)          |
|   \~   |     비트를 1이면 0으로, 0이면 1로 반전 시킴. (비트 NOT 연산, 1의 보수)     |
|   <<   |       명시된 수만큼 비트들을 전부 왼쪽으로 이동시킴. (left shift 연산)      |
|   >>   | 부호를 유지하면서 지정한 수만큼 비트를 전부 오른쪽으로 이동시킴. (right shift 연산) |
|   >>>  |     지정한 수만큼 비트를 전부 오른쪽으로 이동 시키며, 새로운 비트는 전부 0이 됨.     |

* 비트 연산자는 값을 <mark style="color:blue;">비트 단위로 연산</mark>합니다.&#x20;

* 따라서 0과 1로 표현이 가능한 <mark style="color:blue;">정수형이나 형변환이 가능한 자료형</mark>만 연산이 가능합니다.

* 아래 예제코드로 학습해 보겠습니다.

{% code lineNumbers="true" %}

```java
class Operator7_2 {
    public static void main(String[] args) {
        int num1 = 8, num2 = -8;
        System.out.println("8의 2진수 = " + Integer.toBinaryString(num1)); // 0 생략 가능!
        System.out.println("-8의 2진수 = " + Integer.toBinaryString(num2));
        System.out.println("-9의 2진수 = " + Integer.toBinaryString(-9)); // 32bit, int = 4byte

        // 00000000000000000000000000001000 ,  8
        // 11111111111111111111111111111000 , -8
        System.out.println("& 연산자에 의한 결과 = " + (num1 & num2)); // 00000000000000000000000000001000, 8
        System.out.println("| 연산자에 의한 결과 = " + (num1 | num2)); // 11111111111111111111111111111000, -8
        System.out.println("^ 연산자에 의한 결과 = " + (num1 ^ num2)); // 11111111111111111111111111110000, -16

        System.out.println("~ 연산자에 의한 결과 = " + ~num1); // 11111111111111111111111111110111, -9

        System.out.println("<< 연산자에 의한 결과 = " + (num1 << 2)); // 32
        System.out.println(">> 연산자에 의한 결과 = " + (num2 >> 2)); // -2

        System.out.println(">>> 연산자에 의한 결과 = " + (num2 >>> 2)); // 1073741822
    }
}
```

{% endcode %}

* 아마 여기서 \~ 의 <mark style="color:blue;">1의 보수방식</mark>이 이해가 바로 되지 않으실 겁니다.
* 이해를 돕기위해 <mark style="color:blue;">음수표현 방식</mark>을 간단하게 학습하고 가겠습니다.

## 2진수의 음수표현

> ### 진수의 음수를 표현하는 방식에는 <mark style="color:blue;">부호 절대값</mark>, <mark style="color:blue;">1의 보수</mark>, <mark style="color:blue;">2의 보수</mark>가 있습니다.
>
> * 8비트 기준으로 설명하겠습니다.

### 부호 절대값

* 가장 왼쪽에 있는 비트를 <mark style="color:blue;">부호비트</mark>라고 했을 때 이 부호비트가 <mark style="color:blue;">'0인지 1인지'</mark> 에 따라 <mark style="color:blue;">양수</mark>, <mark style="color:blue;">음수</mark>로 구분됩니다.

> #### 0일때는 양수 , 1일때는 음수&#x20;
>
> * 2진수 00000011 = 10진수: 3
> * 2진수 10000011 = 10진수: -3

### 1의 보수

* 1의 보수는 <mark style="color:blue;">11111111 - x</mark> 를 하는 방식입니다.
* 11111111 - x 는 <mark style="color:blue;">x 를 반전</mark>시킨 것과 같습니다.

> #### 11111111 - 00101001 = 11010110
>
> * 즉, <mark style="color:blue;">1이면 0</mark>, <mark style="color:blue;">0이면 1</mark>이 됩니다.

> #### -13을 1의 보수 방식으로 표현해 보겠습니다.
>
> 1. 13을 2진수로 표현 : 00001101
> 2. 11111111 - x 공식에 대입
> 3. 결과 : 11110010

### 2의 보수

* 가장 많이 사용하는 방식입니다.
* 2의 보수는 <mark style="color:blue;">100000000 - x</mark> 를 하는 방식입니다.
* 2의 보수 방식도 가장 <mark style="color:blue;">왼쪽숫자</mark>가 <mark style="color:blue;">0일 경우 양수</mark>, <mark style="color:blue;">1일 경우 음수</mark>를 표현합니다.

> #### -13을 2의 보수 방식으로 표현해 보겠습니다.
>
> 1. 13을 2진수로 표현 : 00001101
> 2. 100000000 - x 공식에 대입
> 3. 결과 : 11110011

* 쉽게 계산하는 방법은 <mark style="color:blue;">1의 보수</mark>를 구한뒤에 <mark style="color:blue;">나온수에 +1</mark>을 하면 됩니다.

> #### -9를 2의 보수 방식으로 표현해 보겠습니다.
>
> 1. -9를 1의 보수 방식으로 표현 : 00001001(9) -> 11110110
> 2. 11110110 + 1
> 3. 결과 : 11110111

{% hint style="info" %}
Ref. Java의 정석 기초편 Chapter3(15, 16)

Ref. [논리 연산자](https://www.youtube.com/watch?v=AdFrJizyF80\&list=PLW2UjW795-f6xWA2_MUhEVgPauhGl3xIp\&index=30)
{% endhint %}
