JavaRush /Java Blog /Random-KO /Java의 비트 연산

Java의 비트 연산

Random-KO 그룹에 게시되었습니다
당신은 아마도 "비트"라는 단어에 익숙할 것입니다. 그렇지 않다면 알아봅시다 :) 비트는 컴퓨터에서 정보를 측정하는 최소 단위입니다. 그 이름은 영어 " 이진수 "- "이진수"에서 유래되었습니다. 비트는 1 또는 0의 두 숫자 중 하나로 표현될 수 있습니다. 1과 0을 기반으로 하는 특수 숫자 시스템인 이진수가 있습니다. 우리는 수학의 정글을 탐구하지 않을 것이며 Java의 모든 숫자는 이진 형식으로 변환될 수 있다는 점만 참고할 것입니다. 이렇게 하려면 래퍼 클래스를 사용해야 합니다. 비트 연산 - 1예를 들어 숫자에 대해 이를 수행하는 방법은 다음과 같습니다 int.
public class Main {

   public static void main(String[] args) {

       int x = 342;
       System.out.println(Integer.toBinaryString(x));
   }
}
콘솔 출력:

101010110
1010 10110(가독성을 위해 공백을 추가했습니다)은 이진수로 된 숫자 342입니다. 우리는 실제로 이 숫자를 개별 비트(0과 1)로 나눴습니다. 우리는 비트 단위라는 연산을 수행할 수 있습니다.
  • ~— 비트 "NOT" 연산자.

매우 간단하게 작동합니다. 숫자의 각 비트를 살펴보고 그 값을 반대 방향으로 변경합니다. 즉, 0에서 1로, 1에서 0으로 변경됩니다. 이를 숫자 342에 적용하면 다음과 같습니다. 101010110은 이진수 342입니다. 010101001은 ~342 표현식의 결과입니다. 그러나 int 변수는 4바이트를 차지하므로, 즉 32비트, 실제로 변수의 숫자는 다음과 같이 저장됩니다. 00000000 00000000 00000001 01010110- Java에서 int 유형의 변수에 있는 숫자 342 11111111 11111111 11111110 10101001- Java에서 ~342 표현식의 결과 실제로 이를 시도해 보겠습니다.
public class Main {

   public static void main(String[] args) {

       int x = 342;
       System.out.println(Integer.toBinaryString(~x));
   }
}
콘솔 출력:
11111111111111111111111010101001
  • &— 비트 연산자 "AND"

보시다시피 논리 “AND”( &&)와 매우 유사하게 작성됩니다. &&기억하시겠지만 연산자는 true두 피연산자가 모두 참인 경우에만 반환됩니다. Bitwise도 &비슷한 방식으로 작동합니다. 즉, 두 숫자를 비트 단위로 비교합니다. 이 비교의 결과는 세 번째 숫자입니다. 예를 들어 숫자 277과 432를 생각해 보겠습니다. 100010101 - 이진 형식의 숫자 277 110110000 - 이진 형식의 숫자 432 다음으로 연산자는 상위 &숫자의 첫 번째 비트와 하위 숫자의 첫 번째 비트를 비교합니다. 이는 "AND" 연산자이므로 두 비트가 모두 1인 경우에만 결과가 1이 됩니다. 다른 모든 경우에는 결과가 0이 됩니다. 100010101 & 110110000 _______________ 100010000 - 작업 결과 & 먼저 첫 번째 비트를 비교합니다. 두 숫자가 서로 결합된 다음 두 번째 비트, 세 번째 등이 됩니다. 보시다시피 숫자의 두 비트가 모두 1(첫 번째 및 다섯 번째 비트)인 경우는 두 가지뿐입니다. 다른 모든 비교 결과는 0이었습니다. 따라서 결국 우리는 100010000이라는 숫자를 얻었습니다. 십진수 체계에서는 숫자 272에 해당합니다. 확인해 보겠습니다.
public class Main {

   public static void main(String[] args) {
       System.out.println(277&432);
   }
}
콘솔 출력:

272
  • |- 비트별 “OR”. 작동 원리는 동일합니다. 두 숫자를 조금씩 비교합니다. 이제 비트 중 하나 이상이 1이면 결과는 1이 됩니다. 동일한 숫자인 277과 432를 살펴보겠습니다.
100010101 | 110110000 _______________ 110110101 - 작업 결과 | 여기서 결과는 다릅니다. 두 숫자 모두에서 0이었던 비트만 0으로 유지되었습니다. 작업 결과는 110110101이라는 숫자입니다. 십진수 체계에서는 437이라는 숫자에 해당합니다. 확인해 보겠습니다.
public class Main {

   public static void main(String[] args) {
       System.out.println(277|432);
   }
}
콘솔 출력:

437
우리는 모든 것을 정확하게 계산했습니다! :)
  • ^- 비트 배타적 OR(XOR이라고도 함)
우리는 이전에 그러한 연산자를 만난 적이 없습니다. 그러나 그것에 대해 복잡한 것은 없습니다. 일반적인 "또는"처럼 보입니다. 차이점은 하나입니다. 일반적인 "or"는 true하나 이상의 피연산자가 true인 경우 반환됩니다. 하지만 반드시 하나만 있는 것은 아닙니다. 둘 다 있으면 true결과가 나옵니다 true. 그러나 배타적인 "or"는 true피연산자 중 하나가 참인 경우에만 반환됩니다. 두 피연산자가 모두 true이면 일반 "or"가 반환되지만 true("적어도 하나는 true") 배타적 or가 반환됩니다 false. 그래서 독점이라고 합니다. 이전 비트 연산의 원리를 알면 277^432 연산을 직접 쉽게 수행할 수 있을 것입니다. 하지만 다시 한 번 함께 알아 보는 것이 좋습니다 :) 100010101 ^ 110110000 _______________ 010100101 - 작업 결과 ^ 여기에 우리의 결과가 있습니다. 두 숫자 모두에서 동일한 비트는 0을 반환했습니다("하나" 공식이 작동하지 않음). 하지만 0-1이나 1-0으로 짝을 이루던 이들은 결국 하나의 유닛으로 변했다. 결과적으로 우리는 010100101이라는 숫자를 얻었습니다. 십진수 체계에서는 숫자 165에 해당합니다. 올바르게 계산했는지 살펴보겠습니다.
public class Main {

   public static void main(String[] args) {
       System.out.println(277^432);
   }
}
콘솔 출력:

165
감독자! 모든 것이 우리가 생각했던 것과 똑같습니다. :) 이제 비트 시프트라고 불리는 작업에 대해 알아볼 시간입니다. 원칙적으로 이름은 그 자체로 말합니다. 숫자를 가져와서 비트를 왼쪽과 오른쪽으로 이동해 보겠습니다. :) 어떻게 보이는지 살펴보겠습니다.

왼쪽으로 이동

비트의 왼쪽 이동은 기호로 표시됩니다 << . 예:
public class Main {

   public static void main(String[] args) {
       int x = 64;//meaning
       int y = 3;//quantity

       int z = (x << y);
       System.out.println(Integer.toBinaryString(x));
       System.out.println(Integer.toBinaryString(z));
   }
}
이 예에서는 숫자를 x=64값이라고 합니다. 우리가 바꿀 부분은 바로 그것입니다. 비트를 왼쪽으로 이동하겠습니다(부호의 방향에 따라 결정될 수 있음 <<). 이진법에서는 숫자 64 = 1000000 이 숫자를 y=3수량이라고 합니다. 수량은 "숫자의 비트를 오른쪽/왼쪽으로 몇 비트만큼 이동해야 합니까 x?"라는 질문에 답합니다. 이 예에서는 왼쪽으로 3비트 이동합니다. 교대 과정을 더 명확하게 하기 위해 그림을 살펴보겠습니다. 이 예에서는 int 유형의 숫자를 사용합니다. Int은 컴퓨터 메모리의 32비트를 차지합니다. 원래 숫자 64는 다음과 같습니다. 비트 연산 - 2이제 문자 그대로의 의미에서 각 비트를 가져와 3셀씩 왼쪽으로 이동합니다. 비트 연산 - 3이것이 우리가 얻은 것입니다. 보시다시피 모든 비트가 이동되었으며 범위 외부에서 3개의 0이 추가되었습니다. 3 - 3만큼 이동했기 때문입니다. 10만큼 이동했다면 10개의 0이 추가됩니다. 따라서 표현은 x << y"숫자 хy 셀의 비트를 왼쪽으로 이동"을 의미합니다. 우리 표현의 결과는 숫자 1000000000이었고, 이는 십진법으로 512와 같습니다. 확인해 봅시다:
public class Main {

   public static void main(String[] args) {
       int x = 64;//meaning
       int y = 3;//quantity

       int z = (x << y);
       System.out.println(z);
   }
}
콘솔 출력:

512
좋아요! 이론적으로 비트는 무한정 이동할 수 있습니다. 하지만 숫자가 있으므로 int사용 가능한 셀은 32개뿐입니다. 이 중 7곳은 이미 64번(100만)이라는 숫자가 차지하고 있다. 따라서 예를 들어 왼쪽으로 27번 이동하면 유일한 유닛이 범위를 벗어나 "덮어쓰기"됩니다. 0만 남습니다!
public class Main {

   public static void main(String[] args) {
       int x = 64;//meaning
       int y = 26;//quantity

       int z = (x << y);
       System.out.println(z);
   }
}
콘솔 출력:

0
예상대로 32비트 셀을 넘어서서 사라졌습니다. 우리는 0으로만 구성된 32비트 숫자를 얻었습니다. 비트 연산 - 4당연히 십진법에서는 0에 해당합니다. 왼쪽 시프트를 기억하는 간단한 규칙: 각 왼쪽 시프트마다 숫자에 2를 곱합니다. 예를 들어, 비트가 있는 그림 없이 표현식의 결과를 계산해 보겠습니다 111111111 << 3 . 숫자 111111111에 2를 세 번 곱하면 888888888이 됩니다. 코드를 작성하고 확인해 보겠습니다.
public class Main {

   public static void main(String[] args) {
       System.out.println(111111111 << 3);
   }
}
콘솔 출력:

888888888

오른쪽 시프트

기호로 표시됩니다 >>. 그들은 같은 일을 하지만 다른 방향으로만 합니다! :) 바퀴를 재발명하지 말고 동일한 숫자 int 64를 사용하여 이 작업을 수행해 봅시다.
public class Main {

   public static void main(String[] args) {
       int x = 64;//meaning
       int y = 2;//quantity

       int z = (x >> y);
       System.out.println(z);
   }
}
비트 연산 - 5비트 연산 - 6오른쪽으로 2만큼 이동한 결과, 우리 숫자의 두 극단 0이 범위를 벗어나 지워졌습니다. 우리는 숫자 10000을 얻었는데, 이는 십진법으로 숫자 16에 해당합니다. 콘솔에 출력:

16
오른쪽 시프트를 기억하는 간단한 규칙: 각 오른쪽 시프트는 2로 나누고 나머지는 버립니다. 예를 들어, 35 >> 2 이는 35를 2로 2번 나누어 나머지를 버려야 함을 의미합니다. 35/2 = 17(나머지 1 버리기) 17:2 = 8(나머지 1 버리기) 합계 35 >> 2는 8과 같아야 합니다. 확인:
public class Main {

   public static void main(String[] args) {
       System.out.println(35 >> 2);
   }
}
콘솔 출력:

8

Java에서의 작업 우선순위

코드를 작성하거나 읽으면서 여러 작업이 동시에 수행되는 표현식을 자주 접하게 됩니다. 어떤 순서로 수행되는지 이해하는 것이 매우 중요합니다. 그렇지 않으면 결과가 예상치 못한 결과가 나올 수 있습니다. Java에는 많은 작업이 있으므로 모두 특수 테이블로 분리되었습니다.

연산자 우선순위

연산자 상위
접미사 expr++ expr--
단항 ++expr --expr +expr ~ !
곱셈 * / %
첨가물 + -
옮기다 << >> >>>
관계형 < > <= >=대신에
평등 == !=
비트 AND &
비트 배타적 OR ^
비트 포함 OR |
논리 AND &&
논리적 OR ||
세 개 한 벌 ? :
과제 = += -= *= /= %= &= ^= |= <<= >>= >>>=
모든 작업은 왼쪽에서 오른쪽으로 수행되지만 우선 순위를 고려합니다. 예를 들어 다음과 같이 쓰면 int x = 6 - 4/2; 먼저 나누기 연산(4/2)이 수행됩니다. 그녀는 서열 2위이지만 우선순위가 더 높습니다. 괄호나 대괄호는 우선순위를 최대값으로 변경합니다. 아마도 학교에서 이것을 기억할 것입니다. 예를 들어 표현식에 추가하면 int x = (6 - 4)/2; 괄호 안에 계산되므로 빼기가 먼저 수행됩니다. &&표에서 볼 수 있듯이 논리 연산자는 우선순위가 다소 낮습니다. 따라서 대부분 마지막에 실행됩니다. 예: boolean x = 6 - 4/2 > 3 && 12*12 <= 119; 이 표현식은 다음과 같이 실행됩니다.
  • 4/2 = 2

    boolean x = 6 - 2 > 3 && 12*12 <= 119;
  • 12*12 = 144

    boolean x = 6 - 2 > 3 && 144 <= 119;
  • 6-2 = 4

    boolean x = 4 > 3 && 144 <= 119;
  • 다음으로 비교 연산자가 실행됩니다:

    4 > 3 = true

    boolean x = true && 144 <= 119;
  • 144 <= 119 = false

    boolean x = true && false;
  • 그리고 마지막으로 마지막 연산자가 실행됩니다 &&.

    boolean x = true && false;

    boolean x = false;

    예를 들어 더하기 연산자( +)는 비교 연산자 !=("같지 않음")보다 우선순위가 높습니다.

    따라서 표현식에서:

    boolean x = 7 != 6+1;

    먼저 6+1 작업이 수행된 다음 7!=7(false)이 확인되고 마지막에 결과가 false변수 에 할당됩니다 x. 할당은 일반적으로 모든 작업 중에서 우선순위가 가장 낮습니다. 표를 살펴보세요.

휴! 우리 강의는 길었지만 해냈습니다! 이 강의와 이전 강의의 일부를 완전히 이해하지 못하더라도 걱정하지 마세요. 이러한 주제는 앞으로 두 번 이상 다룰 것입니다. 다음은 유용한 링크입니다.
  • 논리 연산자 - 논리 연산에 대한 JavaRush 강의입니다. 곧 연락할 수는 없지만 지금 읽으시면 아무런 해가 없을 것입니다.
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION