달나라 노트

C# : &, |, ^, ~ (비트 논리곱, 비트 논리합, 비트 상호배제, 비트 부정) 본문

C#/C#

C# : &, |, ^, ~ (비트 논리곱, 비트 논리합, 비트 상호배제, 비트 부정)

CosmosProject 2022. 4. 7. 01:01
728x90
반응형

 

 

 

& = 비트 논리곱

| = 비트 논리합

^ = 비트 상호배제

~ = 비트 부정

 

위 4개의 연산자는 모두 2진수 상태에서의 연산을 합니다.

인자로 받은 10진수를 2진수로 변경해서 연산한 후 그 결과를 다시 10진수로 변경해서 return해줍니다.

 

이제 각 연산자가 어떻게 작동하는지를 알아봅시다.

 

 

 

 

1. & (비트 논리곱)

 

using System;

class MyProgram
{
    public static void Main()
    {
        Console.WriteLine(1 & 2);
        Console.WriteLine(2 & 2);
        Console.WriteLine(3 & 2);
        Console.WriteLine(4 & 2);
    }
}


-- Result
0
2
2
0

위 코드를 실행하면 각각 0, 2, 2, 0이라는 결과가 나옵니다.

 

대체 무슨 일이 일어났길래 0, 2, 2, 0이라는 결과가 나오는걸까요?

 

아래 예시를 보고 하나씩 그 과정을 이해해 봅시다.

 

 

 

1 & 2 --> 001 & 010 = 000 --> 0
2 & 2 --> 010 & 010 = 010 --> 2
3 & 2 --> 011 & 010 = 010 --> 2
4 & 2 --> 100 & 010 = 000 --> 0

위 코드에서 다뤄진 각각의 & 연산에 대한 과정은 위와 같습니다.

 

1 & 2를 보면 1과 2를 각각 2진수로 바꿉니다.

그러면 1은 001, 2는 010이 됩니다.

 

보통 프로그래밍에선 True는 1, False는 0입니다.

이진수는 각각의 자리수가 0과 1로 이뤄져있기 때문에 각각의 자리수에 존재하는 1, 0 값을 True, False와 대응해서 논리곱(and) 연산이 가능합니다.

 

001과 010에서 같은 위치의 숫자끼리 논리곱을 진행합니다.

 

각 자리수별 연산은 다음과 같습니다.

1 & 2 --> 001 & 010 = 000 --> 0


   001 = 1
 & 010 = 2
-> 000 = 0

0 & 0은 0입니다.

0 & 1은 0입니다.

1 & 0은 0입니다.

따라서 그 결과는 000이고 이를 10진수로 바꾸면 0입니다.

 

그래서 1 & 2의 결과가 0으로 보이는 것입니다.

 

 

 

사실 제 컴퓨터가 32비트이기 때문에 위 과정을 더 정확하게 나타내면 아래와 같이 총 32자리(32비트)의 연산이 됩니다.

   0000 0000 0000 0000 0000 0000 0000 0001 = 1
 & 0000 0000 0000 0000 0000 0000 0000 0010 = 2
-> 0000 0000 0000 0000 0000 0000 0000 0000 = 0

하지만 앞자리는 모두 0으로 채워지기 때문에 연산의 흐름을 파악하는데에는 크게 문제가 되지 않아서 간단하게 하기 위해 세자리정도만 나타내서 설명한 것입니다. (위 예시에서 숫자를 4개씩 띄워서 쓴 것은 그냥 보기 편하라고 표시한 것입니다. 숫자 사이의 공백은 아무 의미 없고 실제로는 존재하지 않습니다.)

 

이러한 논리곱은 본인의 컴퓨터 또는 기기가 몇비트 기반인지에 따라 다릅니다.

예를들어 1111 11111111 1111 1111 1111 1111 1111 1111 1111을 32비트 환경에서 연산하면

1111 1111은 8자리이기 때문에 아래처럼 왼쪽의 나머지 24자리가 모두 0으로 채워진채로 연산된다고 보면 됩니다.

 

0000 0000 0000 0000 0000 0000 1111 1111 & 1111 1111 1111 1111 1111 1111 1111 1111

   0000 0000 0000 0000 0000 0000 1111 1111
 & 1111 1111 1111 1111 1111 1111 1111 1111
-> 0000 0000 0000 0000 0000 0000 1111 1111

 

 

 

 

이제 3 & 2 연산을 봅시다.

 

3 & 2 --> 011 & 010 = 010 --> 2


   011 = 3
 & 010 = 2
-> 010 = 2

위 연산은 3 & 2의 연산 과정입니다.

3은 011입니다. 2는 010입니다.

011과 010의 각 자리수를 True = 1, False = 0으로 생각하여 논리곱을 실행합니다.

 

0 & 0 -> 0

1 & 1 -> 1

1 & 0 -> 0

 

따라서 결과는 010입니다.

010을 다시 10진수로 바꾸면 2이죠.

그래서 3 & 2의 결과가 2인 것입니다.

 

 

 

 

 

 

 

& 연산자는 이진수를 일정 자리수까지만 남기고싶을 때 사용할 수 있습니다.

0000 0000 0000 0000 0000 0000 0110 1010 & 0000 0000 0000 0000 0000 0000 1111 1111

   0000 0000 0000 0000 0000 0000 0110 1010
 & 0000 0000 0000 0000 0000 0000 1111 1111
-> 0000 0000 0000 0000 0000 0000 0110 1010

위 예시를 보면 0110 10101111 1111과 연산한 것입니다.

32비트 체계라 총 32자리의 이진수끼리 연산을 합니다.

여기서 1111 1111은 모두 1(True)이기 때문에 & 연산의 결과는 0110 1010을 그대로 return시킵니다.

 

너무나 당연한 얘기이죠?

하지만 이걸 아주 잘 이용할 수 있습니다.

 

색상을 표현할 때 사용하는 ARGB 체계를 생각해봅시다.

다음은 하나의 ARGB 값을 이진수로 나타내면 아래와 같습니다. (왜 이진수로 표시하면 저렇게 되는지는 일단 넘어가고 이진수와 ARGB값의 대응관계에 포커스를 맞춥시다.)

Color [A=255, R=153, G=217, B=234]

1111 1111 1001 1001 1101 1001 1110 1010

보통 ARGB는 투명도(A), 빨간색(R), 초록색(G), 파란색(B) 각각에 대한 값으로 이뤄져있습니다.

이때 32비트에서 위 ARGB값은 각각의 자리수별로 나타내는 바가 다릅니다.

 

1111 1111 1001 1001 1101 1001 1110 1010

32비트에서 ARGB를 2진수로 표시하면 각 자리수별로 나타내는 요소는 위와 같습니다.

1111 1111 = 가장 왼쪽 8자리는 투명도(A)를 나타냅니다.

1001 1001 = 그 다음 8자리는 빨간색(R)을 나타냅니다.

1101 1001 = 그 다음 8자리는 초록색(G)을 나타냅니다.

1110 1010 = 마지막 8자리는 파란색(B)을 나타냅니다.

 

위같은 32비트짜리 ARGB값에서 A, R, G, B값을 모두 따로 나눠야 우리가 실제로 A, R, G, B값을 사용할 수 있습니다.

예를들어 빨간색(R)값을 좀 줄인다던지, 아니면 투명도(A)를 좀 줄인다던지 등등의 작업을 할 수 있는것이죠.

 

그러면 32진수에서 각각의 A, R, G, B 값을 어떻게 분리할 수 있을까요?

바로 & 연산자를 이용하면 됩니다.

 

먼저 가장 오른쪽에 있는 B 값을 분리해봅시다.

가장 오른쪽 8자리가 B값이므로 우리는 가장 오른쪽 8자리만 남기면 됩니다.

1111 1111 1001 1001 1101 1001 1110 1010 & 0000 0000 0000 0000 0000 0000 1111 1111

   1111 1111 1001 1001 1101 1001 1110 1010
 & 0000 0000 0000 0000 0000 0000 1111 1111
-> 0000 0000 0000 0000 0000 0000 1110 1010

그러면 위처럼 1111 1111과 &연산을 하면 됩니다.

1111 1111은 가장 오른쪽 8자리를 제외하면 모두 0이기때문에 & 연산에 의해서 가장 오른쪽 8자리는 원본 그대로 return되고 나머지 자리수는 모두 0으로 return됩니다.

즉, 가장 오른쪽 8자리만 남게 되는 것이죠.

 

이렇게 return된 값은 1110 1010입니다.

이것을 10진수로 바꾸게되면 234 입니다.

즉, 위 ARGB값에서 파란색(B)값은 234입니다..

 

 

 

 

1111 1111 1001 1001 1101 1001 1110 1010

이제 여기서 중간에 있는 초록색(G) 값을 뽑아봅시다.

 

중간에 있는 값은 비트 쉬프트 연산자인 >>를 사용해야 합니다.

 

1111 1111 1001 1001 1101 1001 1110 1010 >> 8

먼저 위처럼 오른쪽으로 비트를 8자리씩 옮깁니다.

그러면 아래와 같이 변합니다.

 

0000 0000 1111 1111 1001 1001 1101 1001

이제 초록색 인자가 가장 오른쪽 8자리가 됐죠.

그러면 이 상태의 2진수를 1111 1111과 & 연산 시키는겁니다.

 

0000 0000 1111 1111 1001 1001 1101 1001 & 0000 0000 0000 0000 0000 0000 1111 1111

   0000 0000 1111 1111 1001 1001 1101 1001
 & 0000 0000 0000 0000 0000 0000 1111 1111
-> 0000 0000 0000 0000 0000 0000 1101 1001

위처럼 & 연산을 시킨다면 가장 오른쪽 8자리만 남게 됩니다.

그리고 1101 1001 이 8자리는 초록색(G) 값을 나타내죠.

1101 1001 을 10진수로 바꿔보면 217입니다.

따라서 위 ARGB값에서 초록색(G) 값은 217입니다.

 

 

 

 

 

빨간색(R) 값을 추출해봅시다. 방식은 동일합니다.

 

1111 1111 1001 1001 1101 1001 1110 1010

빨간색(R)을 나타내는 값을 먼저 가장 오른쪽으로 보내야합니다.

 

1111 1111 1001 1001 1101 1001 1110 1010 >> 16

그러면 비트를 오른쪽으로 16칸씩 보내면 됩니다. 따라서 >> 16 연산을 하면 아래와 같이 변합니다.

 

0000 0000 0000 0000 1111 1111 1001 1001

이제 빨간색 인자가 가장 오른쪽 8자리가 됐죠.

그러면 이 상태의 2진수를 1111 1111과 & 연산 시키는겁니다.

 

0000 0000 0000 0000 1111 1111 1001 1001 & 0000 0000 0000 0000 0000 0000 1111 1111

   0000 0000 0000 0000 1111 1111 1001 1001
 & 0000 0000 0000 0000 0000 0000 1111 1111
-> 0000 0000 0000 0000 0000 0000 1001 1001

이렇게 1001 1001 라는 숫자가 남아있게 됩니다.

이것은 당연히 ARGB값에서 빨간색(R) 값의 수치를 나타냅니다.

1001 1001 을 20진수로 바꿔보면 153입니다.

따라서 위 ARGB값에서 빨간색(R) 값은 153입니다.

 

 

 

 

 

투명도(A) 값을 추출해봅시다. 방식은 동일합니다.

 

1111 1111 1001 1001 1101 1001 1110 1010

투명도(A)을 나타내는 값을 먼저 가장 오른쪽으로 보내야합니다.


1111 1111 1001 1001 1101 1001 1110 1010 >> 24

그러면 비트를 오른쪽으로 24칸씩 보내면 됩니다. 따라서 >> 24연산을 하면 아래와 같이 변합니다.

 

0000 0000 0000 0000 0000 0000 1111 1111

이제 투명도(A) 인자가 가장 오른쪽 8자리가 됐죠.

그러면 이 상태의 2진수를 1111 1111과 & 연산 시키는겁니다.

 

0000 0000 0000 0000 0000 0000 1111 1111 & 0000 0000 0000 0000 0000 0000 1111 1111

   0000 0000 0000 0000 0000 0000 1111 1111
 & 0000 0000 0000 0000 0000 0000 1111 1111
-> 0000 0000 0000 0000 0000 0000 1111 1111

이렇게 1111 1111 라는 숫자가 남아있게 됩니다.

이것은 당연히 ARGB값에서 빨간색(R) 값의 수치를 나타냅니다.

1111 1111을 20진수로 바꿔보면 255입니다.

따라서 위 ARGB값에서 투명도(A) 값은 255입니다.

 

투명도(A)값이 255라는 것은 전혀 투명하지 않다는 의미입니다.

0이면 완전히 투명해서 보이지 않는다는 의미이구요.

 

 

 

 

그러면 왜 굳이 2진수를 8자리씩 나눠서 ARGB를 표현하는 것일까요?

ARGB의 4개 요소인 투명도(A), 빨간색(R), 초록색(G), 파란색(B)은 각각 0 ~ 255의 값을 가질 수 있습니다.

 

투명도(A)가 0이면 완전히 투명해서 보이지 않는다는 의미이며, 255라면 완전히 불투명하다는 의미입니다.

빨간색(R)이 0이면 빨간빛 요소가 없다는 것이며 255면 빨간빛 요소가 최대로 들어있다는 의미입니다.

초록색(G)이 0이면 초록빛 요소가 없다는 것이며 255면 초록빛 요소가 최대로 들어있다는 의미입니다.

파란색(B)이 0이면 파란빛 요소가 없다는 것이며 255면 파란빛 요소가 최대로 들어있다는 의미입니다.

 

(A, R, G, B) 요소를 이와 같이 나타냈을 때 각 요소 별 색상 예시는 아래와 같습니다.

(255, 255, 0, 0) -> 완전 불투명한 빨간색입니다.

(255, 0, 255, 0) -> 완전 불투명한 초록색입니다.

(255, 0, 0, 255) -> 완전 불투명한 파란색입니다.

(255, 255, 255, 0) -> 완전 불투명하며 빨강과 초록이 최대값으로 섞인 상태입니다. 이 색상은 빨강과 초록이 섞여서 노란색으로 표시됩니다.

(255, 255, 255, 255) -> 완전 불투명한 흰색입니다.

RGB는 색이 아니라 빛이라고 보면 됩니다. 색은 모든 것이 섞이면 검은색이 되는 것에 반해 빛은 모든 빛이 섞이면 하얀색에 가까워집니다.

따라서 (255, 255, 255, 255) 이것처럼 모든 RGB값이 최대로 섞이면 하얀색으로 표시됩니다.

 

이 얘기를 왜 하는것일까요?

지금까지 ARGB 체계를 설명했는데 A, R, G, B 각 요소가 가질 수 있는 값의 범위는 0~255입니다.

이걸 이진수로 나타내면 0은 0000 0000이며 255는 1111 1111이기 때문에 ARGB의 각 값은 하나의 요소당 8자리의 이진수로 나타낼 수 있습니다.

총 4개의 요소를 나타내야하니 8 * 4 = 32자리가 필요하며 이는 위에서 봤던 32비트 이진수와 동일합니다.

 

그래서 32비트 이진수에서 앞에서부터 A, R, G, B값을 8자리씩 할당해서 나타내는 것이죠.

 

1111 1111 1001 1001 1101 1001 1110 1010

 

1111 1111 -> 투명도(A)

1001 1001 -> 빨강(R)

1101 1001 -> 초록(G)

1110 1010 -> 파랑(B)

 

 

 

 

이렇게 ARGB를 나누는 과정을 C# 코드로 나타내면 다음과 같습니다.

다음 예시는 어떤 이미지에 있는 픽셀 중 하나를 불러와 그 픽셀의 ARGB값을 얻고 A, R, G, B 각각의 요소 값으로 분리하는 코드입니다.

 

using System;
using System.Drawing;

class MyProgram
{
    public static void Main()
    {
        Bitmap bm_img = new Bitmap("C:\\Users\\Public\\arrow.png");

        Color c = bm_img.GetPixel(0, 0);
        int argb = c.ToArgb();
        Console.WriteLine(Convert.ToString(argb, 2));

        int a = (argb >> 24) & 255;
        int r = (argb >> 16) & 255;
        int g = (argb >> 8) & 255;
        int b = (argb >> 0) & 255;
        Console.WriteLine("A -> " + Convert.ToString(a, 2) + " = " + Convert.ToString(a));
        Console.WriteLine("R -> " + Convert.ToString(r, 2) + " = " + Convert.ToString(r));
        Console.WriteLine("G -> " + Convert.ToString(g, 2) + " = " + Convert.ToString(g));
        Console.WriteLine("B -> " + Convert.ToString(b, 2) + " = " + Convert.ToString(b));
    }
}


-- Result
11111111100110011101100111101010
A -> 11111111 = 255
R -> 10011001 = 153
G -> 11011001 = 217
B -> 11101010 = 234

 

11111111100110011101100111101010
A -> 11111111 = 255
R -> 10011001 = 153
G -> 11011001 = 217
B -> 11101010 = 234

위 코드의 결과는 위와 같습니다.

보기 편하게 컬러링을 하면 아래와 같습니다.

 

11111111 10011001 11011001 11101010
A -> 11111111 = 255
R -> 10011001 = 153
G -> 11011001 = 217
B -> 11101010 = 234

 

컬러링을 해보니 A, R, G, B의 각 요소가 합쳐져있는 32비트 이진수값에서 A, R, G, B 각각의 값으로 잘 나뉜 것을 볼 수 있습니다.

 

 

 

 

 

 

 

 

 

 

2. | (비트 논리합)

 

using System;

class MyProgram
{
    public static void Main()
    {
        Console.WriteLine(1 | 2);  // 001 010 = 000
        Console.WriteLine(2 | 2);  // 010 010 = 010
        Console.WriteLine(3 | 2);  // 011 010 = 010
        Console.WriteLine(4 | 2);  // 100 010 = 000
    }
}


-- Result
3
2
3
6

 

비트 논리합도 논리곱과 흐름은 완전히 동일합니다.

 

 

 

1 & 2 --> 001 | 010 = 011 --> 3
2 & 2 --> 010 | 010 = 010 --> 2
3 & 2 --> 011 | 010 = 011 --> 3
4 & 2 --> 100 | 010 = 110 --> 6

단 논리합이기때문에 각 자리수별 논리합(or)이 적용됩니다.

 

 

 

1 & 2 --> 001 | 010 = 011 --> 3


   001 = 1
 | 010 = 2
-> 011 = 3

1 & 2를 보면

1 = 001

2 = 010

이 두 숫자의 각 자리수별 논리합은 011입니다.

 

 

 

 

 

 

위에서 ARGB 얘기를 하면서 & 연산자를 이용해 32비트의 ARGB를 표현한 2진수를 A, R, G, B 각각의 요소로 나눌 수 있다는 것을 알아봤죠.

| 연산자는 반대로 A, R, G, B 각 요소의 8비트 이진수 값을 가지고 하나로 합쳐서 32비트짜리 값으로 합칠 수 있습니다.

 

1111 1111 1001 1001 1101 1001 1110 1010

 

똑같이 위에서 봤던 ARGB 값을 예시로 봅시다.

 

A = 1111 1111

R = 1001 1001

G = 1101 1001

B = 1110 1010

위에서 봤던 ARGB의 각 요소별 값을 2진수로 나타낸겁니다.

사실 위처럼 다루는것은 우리가 각 요소들을 조절하거나 하기에는 좋습니다.

근데 컴퓨터에 전달할때에는 위 값을 모두 연결해서 32비트 형태로 전달해야 합니다.

 

이때 | 연산자를 사용할 수 있습니다.

 

먼저 투명도(A) 입니다.

0000 0000 0000 0000 0000 0000 1111 1111 << 24
1111 1111 0000 0000 0000 0000 0000 0000

 

투명도 값은 1111 1111입니다. 근데 32비트 ARGB 체계에서 투명도는 가장 왼쪽 8자리가 되어야합니다.

따라서 1111 1111을 왼쪽으로 24칸 옮겨야합니다.

그래서 위처럼 << 24 연산을 사용했습니다.

 

 

 

이제 빨강(R)을 봅시다.

0000 0000 0000 0000 0000 0000 1001 1001 << 16
0000 0000 1001 1001 0000 0000 0000 0000

 

빨강(R) 값은 1001 1001입니다. 근데 32비트 ARGB 체계에서 빨강(R) 값은 가장 왼쪽에서부터 9번째 자리부터 시작합니다.

따라서 1001 1001을 왼쪽으로 16칸씩 옮겨야합니다.

그래서 위처럼 << 16 연산을 사용했습니다.

 

 

이제 초록(G)을 봅시다.

0000 0000 0000 0000 0000 0000 1101 1001 << 8
0000 0000 0000 0000 1101 1001 0000 0000

 

초록(G) 값은 1101 1001입니다. 근데 32비트 ARGB 체계에서 초록(G) 값은 가장 왼쪽에서부터 17번째 자리부터 시작합니다.

따라서 1101 1001을 왼쪽으로 8칸씩 옮겨야합니다.

그래서 위처럼 << 8 연산을 사용했습니다.

 

 

이제 파랑(B)을 봅시다.

0000 0000 0000 0000 0000 0000 1110 1010 << 0
0000 0000 0000 0000 0000 0000 1110 1010

 

파랑(B) 값은 1110 1010입니다. 근데 32비트 ARGB 체계에서 파랑(B) 값은 가장 오른쪽 8자리를 사용합니다.

따라서 1110 1010을 왼쪽으로 0칸씩 옮겨야합니다. 파랑 값은 옮길 필요가 없다는것이죠.

그래서 위처럼 << 0 연산을 사용했습니다.

 

        255
153
217
234



이렇게 자리수가 옮겨진(쉬프트된) 모든 값을 나열하면 아래와 같습니다.

 

1111 1111 0000 0000 0000 0000 0000 0000 -> 투명도(A)

0000 0000 1001 1001 0000 0000 0000 0000 -> 빨강(R)

0000 0000 0000 0000 1101 1001 0000 0000 -> 초록(G)

0000 0000 0000 0000 0000 0000 1110 1010 -> 파랑(B)

 

이 모든 숫자를 | 연산을 사용해서 비트 논리합을 하게되면 아래와 같이 우리가 원하던 32비트의 형태로 합쳐진 ARGB 값을 얻을 수 있습니다.

 

1111 1111 1001 1001 1101 1001 1110 1010 

 

 

 

이 과정을 C# 코드로 나타내면 다음과 같습니다.

 

using System;

class MyProgram
{
    public static void Main()
    {
        int a = 255;
        int r = 153;
        int g = 217;
        int b = 234;

        int argb = (a << 24) | (r << 16) | (g << 8) | (b << 0);

        Console.WriteLine("A -> " + Convert.ToString(a, 2));
        Console.WriteLine("R -> " + Convert.ToString(r, 2));
        Console.WriteLine("G -> " + Convert.ToString(g, 2));
        Console.WriteLine("B -> " + Convert.ToString(b, 2));
        Console.WriteLine("ARGB -> " + Convert.ToString(argb, 2));
    }
}


-- Result
A -> 11111111
R -> 10011001
G -> 11011001
B -> 11101010
ARGB -> 11111111100110011101100111101010

 

A -> 11111111
R -> 10011001
G -> 11011001
B -> 11101010
ARGB -> 11111111100110011101100111101010

결과를 보면 위와 같습니다.

여기에 보기좋게 컬러링을 하면 다음과 같습니다.

 

A -> 11111111
R -> 10011001
G -> 11011001
B -> 11101010
ARGB -> 11111111 10011001 11011001 11101010

 

잘 합쳐진 것을 볼 수 있습니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

3. ^ (비트 상호배제)

 

using System;

class MyProgram
{
    public static void Main()
    {
        Console.WriteLine(1 ^ 2);  // 001 010 = 000
        Console.WriteLine(2 ^ 2);  // 010 010 = 010
        Console.WriteLine(3 ^ 2);  // 011 010 = 010
        Console.WriteLine(4 ^ 2);  // 100 010 = 000
    }
}


-- Result
3
0
1
6

 

상호배제는 True/False 값이 동일하면 False를 반환하고 다르면 True를 반환합니다.

가능한 경우의 수는 아래와 같습니다.

 

True ^ True -> Flase

True ^ False -> True 

False ^ True -> True 

False ^ False -> Flase

 

 

 

 

1 & 2 --> 001 ^ 010 = 011 --> 3
2 & 2 --> 010 ^ 010 = 000 --> 0
3 & 2 --> 011 ^ 010 = 001 --> 1
4 & 2 --> 100 ^ 010 = 111 --> 6

각 연산 별 과정은 위와 같습니다.

2진수의 동일한 자리수를 비교해서 동일한 값이면 False(0)을 return하고 다른 값이면 True(1)를 return합니다.

 

 

1 & 2 --> 001 ^ 010 = 011 --> 3


   001 = 1
 | 010 = 2
-> 011 = 3

 

 

 

 

 

 

 

4. ~ (비트 부정)

지금까지는 2개의 숫자를 비교해서 어떠한 연산을 했습니다.

하지만 ~ (비트 부정)은 딱 하나의 숫자에 적용해서 2진수의 모든 값을 뒤집어버립니다.

~ 라는 기호는 보통 True 또는 False값을 반전시키는 기능이기 때문입니다.

 

using System;

class MyProgram
{
    public static void Main()
    {
        Console.WriteLine(~1);
        Console.WriteLine(~2);
        Console.WriteLine(~3);
        Console.WriteLine(~4);
    }
}


-- Result
-2
-3
-4
-5

위 예시는 1, 2, 3, 4라는 10진수 숫자에 ~ (비트 부정)을 적용했을 때의 결과입니다.

 

일단 알아야할 것은 제 컴퓨터가 32비트이기 때문에 위 부정은 32비트를 기준으로 이뤄집니다.

 

 

 

0000 0000 0000 0000 0000 0000 0000 0001 = 1
1111 1111 1111 1111 1111 1111 1111 1110 = -2

위 예시는 ~1에 대한 연산 과정입니다.

 

1을 2진수로 나타내면 1인데 32비트에서는 총 32 자리의 2진수가 존재합니다.

따라서 1을 제외한 왼쪽에 있는 자리수는 모두 0으로 채워지죠.

 

여기에 ~ (비트 부정)을 적용하면 모든 자리에 대해 값을 반전시킵니다.

1111 1111 1111 1111 1111 1111 1111 1110이라는 값이 되는 것이죠.

이것은 2의 보수 방식을 사용하는 컴퓨터에서 10진수로 -2를 의미하는 숫자입니다.

 

2의 보수와 2진수의 음수 표시 같은 경우는 아래 링크를 참고하면 이해하기 더 편할겁니다.

https://cosmosproject.tistory.com/569

 

2진수의 음수표현 (부호 절대값, 1의 보수, 2의 보수)

컴퓨터와 같이 기계에서 2진수의 음수를 표현하는 방법을 알아봅시다. 1. 부호 절대값 방식 부호 절대값 방식은 2진수의 가장 왼쪽에 존재하는 0 또는 1값을 + 또는 - 부호로 인식하는 방식입니다.

cosmosproject.tistory.com

 

 

 

 

 

 

728x90
반응형
Comments