비트 연산자의 실제 사용 사례 [닫기]


224

다음 비트 연산자의 실제 사용 사례는 무엇입니까?

  • XOR
  • 아니
  • 또는
  • 왼쪽 / 오른쪽 이동

1
내가 처음 그들에 대해 배웠을 때 그것들은 저수준 c에만 사용되는 것처럼 보였지만 그 이후로 도구 상자에 의해 입력되어 "고수준"프로그래밍을 할 때를 포함하여 자주 사용합니다. 그들은 지금 나를 위해 +와 *와 같습니다.
Oak

2
@Anon .: 내 생각에 현실 세계는 비트 연산자의 가장 명백한 사용 인 저수준 프로그래밍 이외의 것을 의미하는 것으로 생각되었습니다.
Olivier Lalonde



이진 XOR을 사용하여 순열에서 누락 된 숫자를 찾을 수도 있습니다. martinkysel.com/codility-permmissingelem-solution
Janac Meena

답변:


216
  • 비트 필드 (플래그)
    여러 "예 또는 아니오"속성으로 상태가 정의 된 것을 나타내는 가장 효율적인 방법입니다. ACL이 좋은 예입니다. 4 개의 개별 권한 (읽기, 쓰기, 실행, 정책 변경)을 말한 경우이를 낭비보다 1 바이트로 저장하는 것이 좋습니다. 추가 편의를 위해 여러 언어로 열거 유형에 맵핑 할 수 있습니다.

  • 포트 / 소켓을 통한 통신
    은 항상 체크섬, 패리티, 정지 비트, 흐름 제어 알고리즘 등을 포함합니다. 매체는 1 비트 만 전송할 수 있기 때문에 일반적으로 숫자 값이 아닌 개별 바이트의 논리 값에 의존합니다. 시간.

  • 압축, 암호화이
    두 가지 모두 비트 알고리즘에 크게 의존합니다. 예제 는 deflate 알고리즘을 살펴보십시오. 모든 것이 바이트가 아니라 비트 단위입니다.

  • 유한 상태 머신
    소프트웨어에서도 찾을 수 있지만 주로 하드웨어에 내장 된 종류를 말합니다. 이들은 자연에서 조합 - 그들은 말 그대로 논리 게이트의 무리에 아래로 "컴파일"점점 될 수있다, 그들은 다음과 같이 표현 될 필요가 있으므로 AND, OR, NOT, 등

  • 그래픽 이 연산자가 그래픽 프로그래밍에 사용되는 모든 영역에 들어갈 공간이 충분하지 않습니다. XOR(또는 ^)는 동일한 입력을 두 번 적용하면 첫 번째가 실행 취소되므로 여기에서 특히 흥미 롭습니다. 이전 GUI는 값 비싼 다시 그리기의 필요성을 제거하기 위해 선택 강조 표시 및 기타 오버레이에이 방법을 사용했습니다. 느린 그래픽 프로토콜 (예 : 원격 데스크톱)에 여전히 유용합니다.

그것들은 내가 생각해 낸 처음 몇 가지 예일뿐입니다.


안녕하세요 @Aaronaught, 당신은 정말 좋은 지식을 우리와 공유했습니다. Bitwise Operator의 실제 사례에 대해 더 알고 싶습니다. 우리와 참고 자료를 공유해 주시겠습니까? 그것에 대해 더 많이 읽으면 정말 도움이 될 것입니다.
Heena Hussain

비트 단위 연산은 벡터화 가능한 계산에 유용합니까?
Aaron Franke

47

이상한가요?

(value & 0x1) > 0

2로 나눌 수 있습니까?

(value & 0x1) == 0

3
언어 값에 따라 & 0x1> 0은 값 & (0x1> 0)으로 구문 분석 될 수 있습니다.
leeeroy

3
@leeeroy-충분합니다. 일부 괄호가 추가되었습니다.
세스

최신 옵티마이 저는 (value % 2)! = 0과 같은 표현식을 위의 표현식으로 자동 변환합니다. godbolt.org/z/mYEBH4
Ferrarezi

26

다음은 개별 비트로 저장된 플래그를 다루는 일반적인 관용구입니다.

enum CDRIndicators {
  Local = 1 << 0,
  External = 1 << 1,
  CallerIDMissing = 1 << 2,
  Chargeable = 1 << 3
};

unsigned int flags = 0;

청구 가능 플래그를 설정하십시오.

flags |= Chargeable;

CallerIDMissing 플래그 지우기 :

flags &= ~CallerIDMissing;

CallerIDMissing 및 Chargeable이 설정되어 있는지 테스트하십시오.

if((flags & (CallerIDMissing | Chargeable )) == (CallerIDMissing | Chargeable)) {

}

25

CMS의 보안 모델을 구현할 때 비트 단위 연산을 사용했습니다. 적절한 그룹에 있으면 사용자가 액세스 할 수있는 페이지가 있습니다. 사용자는 여러 그룹에 속할 수 있으므로 사용자 그룹과 페이지 그룹간에 교차가 있는지 확인해야했습니다. 따라서 각 그룹에 고유 한 2의 거듭 제곱 식별자를 할당했습니다. 예 :

Group A = 1 --> 00000001
Group B = 2 --> 00000010
Group C = 3 --> 00000100

이 값들을 함께 OR하고 값을 페이지와 함께 단일 int로 저장합니다. 예를 들어 그룹 A & B가 페이지에 액세스 할 수있는 경우 페이지 액세스 제어로 값 3 (2 진은 00000011)을 저장합니다. 거의 같은 방식으로 ORed 그룹 식별자 값을 사용자와 함께 저장하여 그룹을 나타냅니다.

따라서 지정된 사용자가 주어진 페이지에 액세스 할 수 있는지 확인하려면 값을 함께 AND하고 값이 0이 아닌지 확인하면됩니다. 이 검사는 단일 명령, 루핑, 데이터베이스 왕복없이 구현되므로 매우 빠릅니다.


24

저수준 프로그래밍이 좋은 예입니다. 예를 들어, 일부 하드웨어가 원하는 작업을 수행하도록 메모리 매핑 된 레지스터에 특정 비트를 작성해야 할 수 있습니다.

volatile uint32_t *register = (volatile uint32_t *)0x87000000;
uint32_t          value;
uint32_t          set_bit   = 0x00010000;
uint32_t          clear_bit = 0x00001000;

value = *register;            // get current value from the register
value = value & ~clear_bit;   // clear a bit
value = value | set_bit;      // set a bit
*register = value;            // write it back to the register

또한, htonl()htons()사용하여 구현 &하고 |(그 시스템에 연산자를 엔디안 (바이트 순서) 네트워크 순서와 일치하지 않습니다)

#define htons(a) ((((a) & 0xff00) >> 8) | \
                  (((a) & 0x00ff) << 8))

#define htonl(a) ((((a) & 0xff000000) >> 24) | \
                  (((a) & 0x00ff0000) >>  8) | \
                  (((a) & 0x0000ff00) <<  8) | \
                  (((a) & 0x000000ff) << 24))

7
모든 사람이 기계에서 말하는 것은 아닙니다. 두 번째 예는 무엇입니까?
ChaosPandion

7
htons()htonl()스왑하기 POSIX 함수이다 short또는이 long호스트 (로부터 h네트워크 (행) 엔디안 n) 바이트 순서.
Carl Norum

비슷한 방법을 사용하여 O (logN) 연산에서 비트 반전을 수행 할 수 있습니다.
Mike DeSimone

내가 이것을 처음 보았을 때 나는 그것이 조립이라고 생각했다!
0x499602D2

하지가 htonl()32 비트에 대한 int가치인가? long많은 언어에서 64 비트를 의미합니다.
Aaron Franke

21

예를 들어 팩 색상 값에서 RGB (A) 값을 가져 오는 데 사용합니다.


그리고 그것은 정말 빨리합니다!
Callum Rogers

C #에서는 가독성과 속도면에서 정말 최고의 솔루션 인 사례 중 하나입니다.
CaptainCasey 2018 년

4
내 컴퓨터에서 (a & b) >> c보다 a % d / e(ARGB를 나타내는 int에서 단일 색상 값을 추출하는 두 가지 방법) 보다 5 배 이상 빠릅니다 . 각각 10 억 반복에 대해 6.7 및 35.2입니다.
Benji XVI

@ BenjiXVI C #에는 이에 대한 컴파일러 최적화가 있습니다. 속도 차이를 관찰하는 이유는 C # %에서 모듈러스 연산자가 아니라 나머지 연산자이기 때문입니다. 양수 값과 동일하지만 음수 값과 다릅니다. 적절한 제한을 제공하는 경우 ( 예 : uint대신에 전달 int) 두 예제의 속도는 동일해야합니다.
Aaron Franke

죄송합니다. 오랜 시간이 지났습니다. 모든 단일 RGB 값을 얻는 데 사용하는 방법의 예를 보여 주시겠습니까?
징크스

14

부울 플래그가 많으면 모두 int에 저장하는 것을 좋아합니다.

비트 단위 AND를 사용하여 가져옵니다. 예를 들면 다음과 같습니다.

int flags;
if (flags & 0x10) {
  // Turn this feature on.
}

if (flags & 0x08) {
  // Turn a second feature on.
}

기타


23
바라건대 그것들은 실제로 실제 코드에서 상수이며 마법의 숫자가 아닙니다 :)
Earlz

1
저수준이 아닌 환경에서 부울 플래그를 사용하는 한 가지 예는 다양한 GUI 플랫폼으로 작업하는 것입니다. 예를 들어 my_button.Style | = STYLE_DISABLED를 사용하여 끌 수 있습니다.
MauriceL

1
나는이 주제가 언어에 구애받지 않는다는 것을 알고 있지만 C는 비트 필드 로이 작업을 수행하는 쉬운 방법을 제공 하므로 이와 같은 것을 사용할 수 있습니다 if (flags.feature_one_is_one) { // turn on feature }. ANSI C 표준에 있으므로 이식성이 문제가되지 않습니다.
polandeer 2018 년

이 코드 스 니펫이 무엇을하는지, 왜 플래그가 초기화되지 않았는지, "int에 모두 저장"한다는 의미, 사용 된 표기법에 대해 설명하는 것이 좋을 것입니다.
Angelo Oparah

12

& = AND :
특정 비트를 마스크 처리합니다.
표시되거나 표시되지 않아야하는 특정 비트를 정의하고 있습니다. 0x0 & x는 바이트의 모든 비트를 지우고 0xFF는 x를 변경하지 않습니다. 0x0F는 하위 니블의 비트를 표시합니다.

변환 :
비트 ID를 사용하여 더 짧은 변수를 더 긴 변수로 캐스트하려면 int의 -1은 0xFFFFFFFF이고 긴 -1은 0xFFFFFFFFFFFFFFFFFF이므로 비트를 조정해야합니다. 동일성을 유지하기 위해 변환 후 마스크를 적용합니다.

| = OR
비트를 설정하십시오. 비트가 이미 설정되어 있으면 비트가 독립적으로 설정됩니다. 많은 데이터 구조 (비트 필드)에는 IS_HSET = 0, IS_VSET = 1과 같은 플래그가 있으며이 플래그는 독립적으로 설정할 수 있습니다. 플래그를 설정하려면 IS_HSET | IS_VSET (C와 어셈블리에서는 읽기가 매우 편리합니다)

^ = XOR
동일하거나 다른 비트를 찾습니다.

~ = NOT
플립 비트.

이는 것을 표시 할 수있는 모든 가능한 로컬 비트 동작이 이러한 동작에 의해 구현 될 수있다. 따라서 원하는 경우 비트 연산만으로 ADD 명령어를 구현할 수 있습니다.

멋진 해킹 :

http://www.ugcs.caltech.edu/~wnoise/base2.html
http://www.jjj.de/bitwizardry/bitwizardrypage.html


다음은 초고속 수학 연산에 AS3에서 비트 연산자를 사용하는 훌륭한 예를 제공하는 링크입니다 (그러나 대부분의 언어에 적용될 수 있음). lab.polygonal.de/2007/05/10/bitwise-gems-fast- 정수 - 수학
heavilyinvolved

"NOT" 는 OR이 = ~아니 어야한다고 생각합니다 |=.
Mike DeSimone

For- & = AND왜 모든 비트를 지우고 싶습니까? 왜 수정되지 않은 바이트 버전을 얻고 싶습니까? 그리고 더 낮은 니블과 어떻게해야합니까?
confused00

1
@ confused00 맞습니다. 결과를 무효화하는 더 빠르고 간단한 방법은 xor그 자체입니다. 낮은 니블을 추출해야 할 몇 가지 이유를 생각할 수 있습니다. 특히 그 낮은 니블이 데이터 구조의 일부이고 마스크 또는 OR다른 구조체와 함께 사용하려는 경우 .
James M. Lay

11

암호화는 모두 비트 단위 작업입니다.


4
정말? 암호화 구현은 비트 단위 연산을 사용할 가능성이 있지만 암호화 알고리즘은 일반적으로 비트 표현이 아니라 숫자로 설명됩니다.
콘스탄틴

1
그렇다면 알고리즘 이외의 알고리즘으로 무엇을합니까? 궁금해.
재귀

2
@Constantin : 예를 들어 DES 구현 방법에 대한 설명을 참조하십시오 : ( en.wikipedia.org/wiki/…
Wayne Conrad

1
@recursive, 개인적으로 나에게 묻는다면 암호 알고리즘을 디자인하거나 구현하지 않습니다. 그러나 사람들은 이론적 인 약점을 분석하는 등 많은 일을합니다.
Constantin

@Constantin : 이것에 대해 살펴보십시오. 이것은 (일부) 암호화 알고리즘이 일반적으로 설명되는 방법에 대한 많은 예 중 하나입니다. en.wikipedia.org/wiki/Substitution_box
SyntaxT3rr0r

9

데이터를 해시하는 빠르고 더러운 방법으로 사용할 수 있습니다.

int a = 1230123;
int b = 1234555;
int c = 5865683;
int hash = a ^ b ^ c;

8

^약 3 분 전에 bitwise-XOR ( )을 사용하여 PLC와의 직렬 통신을위한 체크섬을 계산했습니다 ...


7

비트 단위 &는 바이트의 특정 부분을 마스크 / 추출하는 데 사용됩니다.

1 바이트 변수

 01110010
&00001111 Bitmask of 0x0F to find out the lower nibble
 --------
 00000010

특히 시프트 연산자 (<< >>)가 종종 계산에 사용됩니다.


6

이것은 비트 맵 이미지에서 바이트 형식으로 색상을 읽는 예입니다.

byte imagePixel = 0xCCDDEE; /* Image in RRGGBB format R=Red, G=Green, B=Blue */

//To only have red
byte redColour = imagePixel & 0xFF0000; /*Bitmasking with AND operator */

//Now, we only want red colour
redColour = (redColour >> 24) & 0xFF;  /* This now returns a red colour between 0x00 and 0xFF.

이 작은 예제가 도움이 되길 바랍니다 ....


5

오늘날 현대 언어의 추상적 세계에서 그리 많지는 않습니다. File IO는 이미 염두에 두는 쉬운 방법이지만 이미 구현 된 작업에 대해서는 비트 단위 작업을 수행하고 비트 작업을 사용하는 작업은 구현하지 않습니다. 여전히 쉬운 예제로,이 코드는 파일에서 읽기 전용 속성을 제거하여 c #에서 FileMode.Create를 지정하는 새 FileStream과 함께 사용할 수 있도록합니다.

//Hidden files posses some extra attibutes that make the FileStream throw an exception
//even with FileMode.Create (if exists -> overwrite) so delete it and don't worry about it!
if(File.Exists(targetName))
{
    FileAttributes attributes = File.GetAttributes(targetName);

    if ((attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
        File.SetAttributes(targetName, attributes & (~FileAttributes.ReadOnly));

    File.Delete(targetName);
}

사용자 지정 구현에 관한 한 최근의 예가 있습니다. 분산 응용 프로그램의 한 설치에서 다른 설치로 보안 메시지를 보내기위한 "메시지 센터"를 만들었습니다. 기본적으로 전자 메일과 유사하며받은 편지함, 보낼 편지함, 보낸 편지함 등이 포함되어 있지만 읽음 확인으로 배달이 보장되므로 "받은 편지함"및 "보낸 편지함"외에 추가 하위 폴더가 있습니다. 이것이받은 내용은 "받은 편지함"또는 "보낸 폴더"를 일반적으로 정의하기위한 요구 사항이었습니다. 보낸 폴더 중에서 읽은 것과 읽지 않은 것을 알아야합니다. 읽지 않은 것 중에서, 나는 무엇을 받았는지,받지 않은 것을 알아야합니다. 이 정보를 사용하여 로컬 데이터 소스를 필터링하고 적절한 정보를 표시하는 동적 where 절을 작성합니다.

열거 형을 구성하는 방법은 다음과 같습니다.

    public enum MemoView :int
    {
        InboundMemos = 1,                   //     0000 0001
        InboundMemosForMyOrders = 3,        //     0000 0011
        SentMemosAll = 16,                  //     0001 0000
        SentMemosNotReceived = 48,          //     0011
        SentMemosReceivedNotRead = 80,      //     0101
        SentMemosRead = 144,                //     1001
        Outbox = 272,                       //0001 0001 0000
        OutBoxErrors = 784                  //0011 0001 0000
    }

이것이 무엇을하는지 아십니까? "Inbox"열거 형 값 InboundMemos와 함께 (&)를 사용하여 InboundMemosForMyOrders가받은 편지함에 있음을 알고 있습니다.

다음은 현재 선택된 폴더에 대한보기를 정의하는 필터를 빌드하고 반환하는 메소드 버전입니다.

    private string GetFilterForView(MemoView view, DefaultableBoolean readOnly)
    {
        string filter = string.Empty;
        if((view & MemoView.InboundMemos) == MemoView.InboundMemos)
        {
            filter = "<inbox filter conditions>";

            if((view & MemoView.InboundMemosForMyOrders) == MemoView.InboundMemosForMyOrders)
            {
                filter += "<my memo filter conditions>";
            }
        }
        else if((view & MemoView.SentMemosAll) == MemoView.SentMemosAll)
        {
            //all sent items have originating system = to local
            filter = "<memos leaving current system>";

            if((view & MemoView.Outbox) == MemoView.Outbox)
            {
                ...
            }
            else
            {
                //sent sub folders
                filter += "<all sent items>";

                if((view & MemoView.SentMemosNotReceived) == MemoView.SentMemosNotReceived)
                {
                    if((view & MemoView.SentMemosReceivedNotRead) == MemoView.SentMemosReceivedNotRead)
                    {
                        filter += "<not received and not read conditions>";
                    }
                    else
                        filter += "<received and not read conditions>";
                }
            }
        }

        return filter;
    }

매우 단순하지만 일반적으로 비트 단위 연산이 필요하지 않은 추상화 수준의 깔끔한 구현입니다.


4

Base64 인코딩이 예입니다. Base64 인코딩은 이진 데이터를 전자 메일 시스템 (및 기타 목적)을 통해 전송하기위한 인쇄 가능한 문자로 나타내는 데 사용됩니다. Base64 인코딩은 일련의 8 비트 바이트를 6 비트 문자 조회 색인으로 변환합니다. 비트 연산, 시프 팅 및 밍 또는 비핑은 Base64 인코딩 및 디코딩에 필요한 비트 연산을 구현하는 데 매우 유용합니다.

이것은 물론 수많은 예제 중 하나 일뿐입니다.



4

일반적으로 비트 연산은 곱하기 / 나누기보다 빠릅니다. 따라서 변수 x에 9를 곱 해야하는 경우 x<<3 + x보다 몇 사이클 더 빠릅니다 x*9. 이 코드가 ISR 내에 있으면 응답 시간이 절약됩니다.

마찬가지로 배열을 순환 대기열로 사용하려면 비트 단위 작업으로 검사를 감싸는 것이 더 빠르고 우아합니다. (배열 크기는 2의 거듭 제곱이어야합니다). 예 : 삽입 / 삭제하려는 경우 tail = ((tail & MASK) + 1)대신 대신 사용할 수 있습니다 tail = ((tail +1) < size) ? tail+1 : 0.

또한 오류 플래그가 여러 오류 코드를 함께 보유하려는 경우 각 비트는 별도의 값을 보유 할 수 있습니다. 각 개별 오류 코드와 함께 검사 할 수 있습니다. 이것은 유닉스 오류 코드에서 사용됩니다.

또한 n 비트 비트 맵은 정말 시원하고 컴팩트 한 데이터 구조 일 수 있습니다. 크기가 n 인 리소스 풀을 할당하려는 경우 n 비트를 사용하여 현재 상태를 나타낼 수 있습니다.



3

숫자 x는 2의 거듭 제곱입니까? (예를 들어 카운터가 증가하고 로그 횟수 만 수행되는 알고리즘에서 유용합니다.)

(x & (x - 1)) == 0

정수의 가장 높은 비트는 어느 것 x입니까? (예를 들어,이 값보다 큰 최소 전력 2를 찾는 데 사용할 수 있습니다 x)

x |= (x >>  1);
x |= (x >>  2);
x |= (x >>  4);
x |= (x >>  8);
x |= (x >> 16);
return x - (x >>> 1); // ">>>" is unsigned right shift

1정수 의 가장 낮은 비트는 어느 것 x입니까? (2로 나눌 수있는 횟수를 찾는 데 도움이됩니다.)

x & -x

부호없는 오른쪽 시프트는 LHS를 부호없는 유형으로 캐스팅하여 C에서 수행됩니다. 마지막 공식이 가장 낮은 [set] 비트를 찾지 못하면 X가 2의 거듭 제곱인지 확인합니다. 가장 낮은 설정 비트를 찾으려면을 수행하십시오 x & -x.
Potatoswatter

흠, 당신은 옳습니다, 어떻게 든 내가 x & -x를 첫 번째 스 니펫으로 바 꾸었습니다. 편집을 위해 thx
Dimitris Andreou

3

비트 연산자는 길이가 2의 제곱 인 배열을 반복하는 데 유용합니다. 많은 사람들이 언급했듯이 비트 연산자는 매우 유용하며 플래그 , 그래픽 , 네트워킹 , 암호화에 사용 됩니다. 뿐만 아니라 매우 빠릅니다. 개인적으로 가장 좋아하는 것은 조건 없이 배열반복 하는 입니다. 당신이 있다고 가정 제로 인덱스 기반의 배열을 (예를 들어 첫 번째 요소의 인덱스 0) 당신은 그것을 무한 루프가 필요합니다. 무기한으로 나는 첫 번째 요소에서 마지막으로 가고 처음으로 돌아 오는 것을 의미합니다. 이를 구현하는 한 가지 방법은 다음과 같습니다.

int[] arr = new int[8];
int i = 0;
while (true) {
    print(arr[i]);
    i = i + 1;
    if (i >= arr.length) 
        i = 0;
}

if 문 을 사용하지 않으려면 가장 간단한 방법입니다. 모듈러스 방법을 다음과 같이 사용할 수 있습니다 .

int[] arr = new int[8];
int i = 0;
while (true) {
    print(arr[i]);
    i = i + 1;
    i = i % arr.length;
}

이 두 가지 방법의 단점은 정수 나누기 후에 나머지를 찾기 때문에 계수 연산자가 비싸다는 것입니다. 그리고 첫 번째 방법은 각 반복마다 if 문을 실행합니다 . 그러나 비트 연산자를 사용하면 배열의 길이가 2의 거듭 제곱이면 (비트 및) 연산자를 0 .. length - 1사용하여 처럼 시퀀스를 쉽게 생성 할 수 있습니다 . 이것을 알면 위의 코드는&i & length

int[] arr = new int[8];
int i = 0;
while (true){
    print(arr[i]);
    i = i + 1;
    i = i & (arr.length - 1);
}

작동 방식은 다음과 같습니다. 에서는 바이너리 형식 1 감산 (2)의 전력이 각 숫자들만로 표현된다. 예를 들어 이진수의 3은 117 111, 15는 15 등입니다 1111. 이제 &이진수로만 구성된 숫자에 숫자 가 있으면 어떻게됩니까 ? 우리가 이것을한다고 가정 해 봅시다.

num & 7;

num7보다 작거나 같은 경우 결과는 1이있는 num각 비트 &가 자체 이기 때문 입니다. 경우 num7보다 큰는 동안 &작동 컴퓨터 물론 이후 제로로 남아있을 것입니다 제로 선두 (7 개)의 고려하게됩니다 &만 후미 부분이 남아 작업을. 9 & 7이진의 경우 처럼

1001 & 0111

결과는 0001이며 10 진수로 1이고 배열에서 두 번째 요소를 처리합니다.


배열의 길이가 2의 거듭 제곱 인 경우 텍스트의 절반을 첫 문장에 입력해야합니다. 이 트릭을 사용하는 것은 매우 심각한 제한입니다. 개인적으로 나는 어쨌든 이것을 구현하지 않을 것이며, 코드는 if 또는 mod 접근 방식 보다 이해하기 어렵습니다 .
Jan Doggen

@ JanDoggen 당신 말이 맞아요, 첫 문장에 넣겠습니다. 배열이 2의 거듭 제곱에 관해서는, 내 경험상 그 일이 몇 번이나 발생했습니다. 네트워크 및 그래픽과 관련이 있었기 때문일 수 있습니다.
user3552161 2016 년

1
이 게시물의 요점은 비트 연산자가 0, 1, 2, 3, 0, 1, 2의 숫자 시퀀스를 생성하는 데 유용하다는 것을 보여주었습니다. 시퀀스는 처음으로 생각한 것입니다.
user3552161 2016 년

2

다중 선택 옵션에 사용합니다.이 방법으로 10 개 이상의 값 대신 하나의 값만 저장합니다


2

SQL 관계형 모델에서도 유용 할 수 있습니다. BlogEntry, BlogCategory 테이블이 있다고 가정 해 봅시다.

전통적으로 BlogEntryCategory 테이블을 사용하여 그들 사이에 nn 관계를 만들 수 있습니다. 또는 BlogCategory 레코드가 많지 않은 경우 BlogEntry에 하나의 값을 사용하여 플래그가 지정된 열거 형과 마찬가지로 여러 BlogCategory 레코드에 연결할 수 있습니다. 대부분의 RDBMS에는 '플래그'열에서 선택할 수있는 매우 빠른 연산자


2

마이크로 컨트롤러 출력의 일부 비트 만 변경하려고하지만 기록 할 레지스터가 바이트 인 경우 다음과 같은 작업을 수행합니다 (의사 코드).

char newOut = OutRegister & 0b00011111 //clear 3 msb's
newOut = newOut | 0b10100000 //write '101' to the 3 msb's
OutRegister = newOut //Update Outputs

물론 많은 마이크로 컨트롤러를 사용하면 각 비트를 개별적으로 변경할 수 있습니다.


이것은 어떤 언어입니까?
카슨 마이어스

@Carson : 언어가 없습니다. 이것은 의사 코드입니다. 실제로했던 때 그것을 조립했다,하지만 난 그것을 머리 위로, 나는 그것을 명확하게 업데이트 할 수 있습니다에 대한 C. 감사에서 그것을 쉽게 생각 몇 년 전
에밀리오 M Bumachar

주석을 변경하기 위해 답변을 편집하여 강조 표시가 너무 많이 퍼지지 않았습니다. 그리고 내가 볼, 나는 C 될 줄 알았는데하지만 당신은 I의 0B ... 표기법을 사용 소원 C.에서 사용할 수있었습니다
카슨 마이어스

2

숫자 mod (%)를 2의 거듭 제곱으로 계산하려면을 사용할 수 있습니다 yourNumber & 2^N-1.이 경우와 같습니다 yourNumber % 2^N.

number % 16 = number & 15;
number % 128 = number & 127;

이것은 아마도 2 ^ N 인 매우 큰 배당을 가진 모듈러스 연산의 대안으로 만 유용 할 것입니다. 그러나 .NET 2.0의 테스트에서는 모듈러스 연산에 대한 속도 향상이 무시할 만합니다. 현대 컴파일러가 이미 이와 같은 최적화를 수행하고 있다고 생각합니다. 아무도 이것에 대해 더 알고 있습니까?


컴파일러는이 최적화를 사용하지만 최적화에 대해 모른다면 정확한 2의 제수를 선택하지 못할 수도 있습니다.
Ben Voigt

상황에 따라 다릅니다. C #에서는 %나머지 작업 과 마찬가지로 실제로 다른 결과를 생성하므로 음수를 다르게 취급합니다. 그러나 전달하는 경우 uint%, C # 컴파일러가 실제로 비트를 사용하여 기계 코드를 생성하고 두 번째 인수는 2의 미리 알려진 전원이됩니다.
Aaron Franke

1

역할 기반 액세스 제어 시스템에 사용되는 것을 보았습니다.



1

이들은 주로 비트 단위 연산 (놀람)에 사용됩니다. 다음은 PHP 코드베이스에서 볼 수있는 실제 예제입니다.

문자 인코딩 :

if (s <= 0 && (c & ~MBFL_WCSPLANE_MASK) == MBFL_WCSPLANE_KOI8R) {

데이터 구조 :

ar_flags = other->ar_flags & ~SPL_ARRAY_INT_MASK;

데이터베이스 드라이버 :

dbh->transaction_flags &= ~(PDO_TRANS_ACCESS_MODE^PDO_TRANS_READONLY);

컴파일러 구현 :

opline->extended_value = (opline->extended_value & ~ZEND_FETCH_CLASS_MASK) | ZEND_FETCH_CLASS_INTERFACE;

1

C 프로그래밍을 처음 시작할 때마다 진리표와 그 모든 것을 이해했지만이 기사를 읽을 때까지 실제로 그것을 사용하는 방법을 모두 클릭하지는 않았습니다 . (실제 사례를 제공함)


1
아니요, 동일하지 않습니다. 경우 C에서, x == 1그리고 y == 2, 다음 x || y1로 평가하고 x | y0 평가도 아니다 내가보고 할 이유 x^true우수하다 !x어떤 방법이다. 타이핑이 많고 관용적 x이지 않으며 , 그렇지 않으면 bool신뢰할 수 없습니다.
David Thornley

아 잠깐만 .. 응, 그건 내 멍청한 짓이야. 오늘은 똑바로 생각할 수 없어.
Earlz

x | y는 3으로 평가됩니다 (편집 : nvm, 편집 한 내용을 참조하고 있음을 알았습니다!)
Pod

1
@DavidThornley : 하나의 경우 x^true에 우수가 !x있다 some->complicated().member->lookup ^= true; 단항 연산자의 어떤 화합물 할당 버전이 없습니다.
벤 Voigt

1

나는 이것이 비트 단위로 계산되지 않는다고 생각하지만, 루비의 배열은 정상적인 정수 비트 연산자를 통해 집합 연산을 정의합니다. 그래서 [1,2,4] & [1,2,3] # => [1,2]. a ^ b #=> set difference및의 경우 와 유사합니다 a | b #=> union.


1

하노이 타워 선형 솔루션은 비트 단위 연산을 사용하여 문제를 해결합니다.

public static void linear(char start, char temp, char end, int discs)
{
    int from,to;
    for (int i = 1; i < (1 << discs); i++) {
        from = (i & i-1) % 3;
        to = ((i | i-1) + 1) % 3;
        System.out.println(from+" => "+to);
    }
}

이 솔루션에 대한 설명은 여기 에서 찾을 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.