1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ビット演算黒魔術集

Last updated at Posted at 2024-11-18

※ ここでいう黒魔術とは、「マジックナンバーや、あまり一般的でない演算子を使うので、実装はシンプルになるけど、可読性は低いから、その点は注意しようね~」ぐらいの意味です。
※ 符号付き整数を想定しています

トグル

x ^= 1

 0 にこれを作用させると 1 になり、1 にこれを作用させると 0 になります。これを利用して、トグルスイッチみたいに切り替えたり、「ペアのうち片方を指す」みたいな使い方をできたりします。

補数によるペア

~x

 ~ は全ビットを反転させます(補数)。反転前の数を $A$ とすると、 $-A-1$ を返します。

 これの嬉しいポイントとして、ある非負整数に対して一対一対応のペアが作れる ということがあります。

 例えば、非再帰DFSにおいて「行きがけ」と「帰りがけ」のそれぞれのノードを、「ある非負整数」と「その補数」として表現できます。

 参考記事:それ、非再帰で書けます

 ちなみに、補数の関係は以下のようになっています。わかりやすく示すために、$4$ bit符号付整数で考えています。

image.png

「数値の文字」と「数値」の切り替え

c ^= 48

 数値の文字ならばその数値を、数値ならばそれに対応する文字を返します。

なぜそうなるのか

image.png

小文字と大文字の切り替え

c ^= 32

 char 型の文字に対して、小文字ならば大文字を、大文字ならば小文字を返します。

なぜそうなるか

image.png

最も右にあるビットを削除する

x & (x-1)

 その数で立っているビットのうち、最も右にあるものを削除します。

なぜそうなるか

image.png

最も右にあるビットだけを抽出する

x & -x

 上のと似ていますが、その数で立っているビットのうち、最も右にあるだけを抽出します。

なぜそうなるか

image.png

2冪かどうかを判定

x & (x-1) == 0

 上の応用ですが、「1つ以上ビットが立っており、最も右にあるビットを削除したとき、$0$ になる」と「$1$ つのビットだけが立っている」は同値です。そして、$1$ つのビットだけが立っていることは、$2^n$($n$ は非負整数) で表される $2$ 冪の数であることと同値です。

int main(){
    for(int i=1;i<=16;i++){
        bool beki = (i&(i-1)) == 0;
        cout << i << " " << beki << endl;
    }
}
output
1 1
2 1
3 0
4 1
5 0
6 0
7 0
8 1
9 0
10 0
11 0
12 0
13 0
14 0
15 0
16 1

最も近い2冪を出す

 $2$ 冪かどうかの判別と、最右ビットの削除を組み合わせると、最も近い $2$ 冪を出すことができます。

「その数以下で最小の $2$ 冪」を求めます。その数が $2$ 冪ならそのまま、そうでなければ、そうなるまで最右ビットを削除していけばよいです。

int main(){
    for(int i=1;i<=16;i++){
        int x = i;
        while(x&(x-1)){
            x &= x-1;
        }
        cout << i << " " << x << endl;
    }
}
output
1 1
2 2
3 2
4 4
5 4
6 4
7 4
8 8
9 8
10 8
11 8
12 8
13 8
14 8
15 8
16 16

 少し改造すると、「その数以上で最小の $2$ 冪」を出すこともできます。

int main(){
    for(int i=1;i<=16;i++){
        int x = i;
        if(x&(x-1)){
            while(x&(x-1)){
                x &= x-1;
            }
            x <<= 1;
        }
        cout << i << " " << x << endl;
    }
}
output
1 1
2 2
3 4
4 4
5 8
6 8
7 8
8 8
9 16
10 16
11 16
12 16
13 16
14 16
15 16
16 16
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?