ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 유용한 비트연산들 모음
    알고리즘 2022. 2. 17. 06:42

    문자 | 문자열

    대문자와 소문자는 정확히 32만큼 차이 난다. 32는 (1<<n)의 형태이므로, '간단한' 비트 연산을 적용하기 가장 쉽다.

    1. 항상 대문자로 만들기

    char f(char x) { return x & ~32; }

    32를 나타내는 비트만 0으로 놓고, 문자와 AND를 취하면 32의 비트만 끌 수 있다.

     

    2. 항상 소문자로 만들기

    char f(char x) { return x | 32; }

     

    3. toggle (소문자는 대문자로, 대문자는 소문자로)

    char f(char x) { return x ^ 32; }

    정수

     

    1. 2의 지수 형태 판별 :

    bool f(int n) { return !(n & (n - 1)); }

     

    2. 모든 n개의 비트가 켜져 있는지 확인

    bool f(int bt) { return (bt + 1) == (1 << n); }

    비트마스킹 문제를 풀 때 자주 사용된다. n개의 비트를 일일이 켜서 확인하는 건 매우 번거롭지만,

    모든 비트가 1이라면 1을 더했을때 단 한 개의 비트만 1인, 곧 1000...(2)의 형태가 됨을 이용해 간단히 구현할 수 있다.

    여담으로, 순열 완전탐색을 구현할 때 재귀로 해도 간단하지만, [0, (1<<n) )을 탐색해도 된다.

    만약, 공집합이 의미가 없다면 [1, (1<<n) -1 )을 탐색하면 된다.

     

    3. 비트내 켜져 있는 비트 개수 구하기

    int f(int bt) { return __builtin_popcount(bt); }

    직접 하나씩 쉬프트 하며 확인하면 O(logN)이 될 수밖에 없다.

    내부에 조금 복잡한 비트연산 몇 가지로 조합되어 O(1)에 작동하는 __builtin_popcount()를 사용하면

    간단하고도 훌륭한 성능의 구현이 가능하다.

     

    4. 비트내 가장 왼쪽에 켜진 비트 위치 구하기

    int f(int bt) { return 31 - __builtin_clz(bt); }
     
    __builtin_clz()는 가장 왼쪽에 있는 켜진 비트를 기준으로, 왼쪽에 존재하는 비트의 개수를 리턴한다.
     
     
     

    5. 비트내 가장 오른쪽에 켜진 비트 위치 구하기

    int f(int bt) { return __builtin_ctz(bt); }

    clz()에서 왼쪽과 오른쪽만 달라졌다.

     

    6. 비트내 가장 오른쪽에 켜진 비트 구하기

    int f(int bt) { return bt & (-bt); }

    당연히, 4에서 1<<f(bt)를 해도 같은 결과가 나온다.  

     

    7. [s, e]에서 mid 찾기

    int f(int s, int e) { return s + e >> 1; }

    비트연산 쉬프트는 +보다 우선순위가 낮기에, 괄호를 안 붙여도 된다.

    (s+e)/2보다 미세하게 빠르기도 하거니와, 귀찮게 괄호를 열고 닫을 필요가 없음이 유용하다.

    이분탐색, 세그먼트 트리등 mid값은 원체 자주 쓰인다.

     

    8. 정수 n 홀수 판별

    bool f(int n) { return n & 1; }

     


    참고 : http://www.secmem.org/blog/2019/10/19/handy-function-about-bit/

    '알고리즘' 카테고리의 다른 글

    [BFS] 너비 우선 탐색  (0) 2021.10.15
    [냅색] Knapsack Problem  (0) 2021.09.15
    [MST] 최소 스패닝 트리  (0) 2021.09.15
    [정수론] 소수판별  (0) 2021.09.13
    [LPS] Longest Palindrome Substring / Subsequence  (0) 2021.09.03

    댓글