SlideShare a Scribd company logo
明日使えないすごいビット演算
KMC1回生 prime(Twitter id:@_primenumber)
ビット演算とは
●

●

●

コンピューター内で数値や文字列などのデータは2進数で記
録されている
ビット演算とは、2進数を0/1の列として操作するような演算
のこと
ビット反転 (C言語では ~x)
–

各ビットの0/1を反転させる

x

0 1 1 0 1 0 1 1

~x

1 0 0 1 0 1 0 0
ビット演算とは
●

ビット論理和 (C言語では x|y)
–

各桁を比較して、少なくとも一方が1なら1

x
y

0 0 1 0 1 0 1 1

x|y

1 1 1 0 1 0 1 1

1 1 0 0 1 0 0 1
ビット演算とは
●

ビット論理積 (C言語では x&y)
–

各桁を比較して、両方とも1なら1

x
y

0 0 1 0 1 0 1 1

x&y

0 0 0 0 1 0 0 1

1 1 0 0 1 0 0 1
ビット演算とは
●

ビット排他的論理和 (C言語では x^y)
–

各桁を比較して、片方のみが1なら1

x
y

0 0 1 0 1 0 1 1

x^y

1 1 1 0 0 0 1 0

1 1 0 0 1 0 0 1
ビット演算とは
●

左ビットシフト (C言語では x<<n)
–

x

各桁を左に指定した桁数ずらす

0 0 1 0 1 0 1 1

x<<3 0 1 0 1 1 0 0 0
ビット演算とは
●

右ビットシフト (C言語では x>>n)
–

x

各桁を右に指定した桁数ずらす

0 0 1 0 1 0 1 1

x>>3 0 0 0 1 0 1 0 1
上位桁に何を詰めるかによっていくつか種類がある
● 0を詰める
● 元の最上位桁と同じ物を詰める
ビット演算とは
●

ビット演算は回路が単純になるため、とても高速なことが多い
–
–

●

とはいえ最近のCPUだと加減乗算も同じぐらい速い
組み合わせて使うことも多い

うまく使うとものすごい高速化できる
–

●

●

単純な実装に比べて数十倍速くなることも

今回はビット演算を用いていろいろな操作を高速にする例を
挙げます
数値は2の補数表現で格納されているものとします
明日使えないすごいビット演算
●

「1になっている一番下の桁」を取得する
–

2の何乗で割り切れるか,みたいなことが分かったりする

data

0

1

0

1

1

0

0

0
明日使えないすごいビット演算
●

「1になっている一番下の桁」を取得する
–

2の何乗で割り切れるか,みたいなことが分かったりする

data

0

1

0

1

1

0

0

0

0

0

0

0

1

0

0

0
明日使えないすごいビット演算
●

「1になっている一番下の桁」を取得する

data & (-data)
data

0

1

0

1

1

0

0

0

-data

1

0

1

0

1

0

0

0

実は,-dataは~data+1に等しい
(足して0になるようにするため)
明日使えないすごいビット演算
●

「1になっている一番下の桁」を取得する

data & (-data)
data

0

1

0

1

1

0

0

0

-data

1

0

1

0

1

0

0

0

data & (-data) 0

0

0

0

1

0

0

0

実は,-dataは~data+1に等しい
(足して0になるため)
明日使えないすごいビット演算
●

「1になっている一番下の桁」を0にする

data &= data-1
data

0

1

0

1

1

0

0

0

data-1

0

1

0

1

0

1

1

1

data & data-1

0

1

0

1

0

0

0

0
明日使えないすごいビット演算
●

「1になっている一番上の桁」を求める
–
–

●

数値のだいたいの大きさを求める
log2 ( n ) の整数部分を求めるのに使える

これは一発では行かないが、うまい方法がある
明日使えないすごいビット演算
●

「1になっている一番上の桁」を求める
–
–

●

数値のだいたいの大きさを求める
log 2 ( n ) の整数部分を求めるのに使える

これは一発では行かないが、うまい方法がある
–

二分探索!
明日使えないすごいビット演算
●

「1になっている一番上の桁」を求める

0

1

0

1

1

0

0

1

0xF0 1

1

1

1

0

0

0

0

ビット論理積

0

1

0

1

0

0

0

0
明日使えないすごいビット演算
●

「1になっている一番上の桁」を求める

0

1

0

1

1

0

0

1

0xF0 1

1

1

1

0

0

0

0

ビット論理積

0

1

0

1

0

0

0

0

!= 0
明日使えないすごいビット演算
●

「1になっている一番上の桁」を求める

0

1

0

1

1

0

0

1

0xF0 1

1

1

1

0

0

0

0

ビット論理積

0

1

0

1

0

0

0

0

!= 0

1になっている一番上の桁は上位4桁のどれか!
明日使えないすごいビット演算
●

「1になっている一番上の桁」を求める

0

1

0

1

1

0

0

1

0

1

0

1

0

0

0

0

0xCC 1

1

0

0

1

1

0

0

ビット論理積

0

1

0

0

0

0

0

0
明日使えないすごいビット演算
●

「1になっている一番上の桁」を求める

0

1

0

1

1

0

0

1

0

1

0

1

0

0

0

0

0xCC 1

1

0

0

1

1

0

0

ビット論理積

0

1

0

0

0

0

0

0

!= 0

1になっている一番上の桁は上位2桁のどれか!
明日使えないすごいビット演算
●

「1になっている一番上の桁」を求める
–

data
data
data
data
data

サンプルコード(32ビット)
=
=
=
=
=

data
data
data
data
data

&
&
&
&
&

0xFFFF0000
0xFF00FF00
0xF0F0F0F0
0xCCCCCCCC
0xAAAAAAAA

?
?
?
?
?

data
data
data
data
data

&
&
&
&
&

0xFFFF0000
0xFF00FF00
0xF0F0F0F0
0xCCCCCCCC
0xAAAAAAAA

:
:
:
:
:

data;
data;
data;
data;
data;
明日使えないすごいビット演算
●

ビット列を逆転する
–

高速フーリエ変換などで用いる

data

0

1

0

1

1

0

0

1

dataの逆転

1

0

0

1

1

0

1

0
明日使えないすごいビット演算
●

ビット列を逆転する
–

これも一気にやるのは無理

data

0

0

1

data&0x55
data&0xAA

1

0

1

1

1
0

0

0

0
1

1
1

0
明日使えないすごいビット演算
●

ビット列を逆転する

data

0 1 0 1 1 0 0 1

(data&0x55)<<1 1
(data&0xAA)>>1

1
0

0
0

1
1

0
明日使えないすごいビット演算
●

ビット列を逆転する

data

0 1 0 1 1 0 0 1

(data&0x55)<<1 1
(data&0xAA)>>1

1
0

0
0

1
1

0

ビット論理和

1 0 1 0 0 1 1 0
明日使えないすごいビット演算
●

ビット列を逆転する

変更前のdata

0 1 0 1 1 0 0 1

変更後のdata

1 0 1 0 0 1 1 0
明日使えないすごいビット演算
●

ビット列を逆転する

0 1 0 1 1 0 0 1
変更後のdata

1 0 1 0 0 1 1 0

data&0x33
data&0xCC 1 0

1 0

1 0
0 1
明日使えないすごいビット演算
●

ビット列を逆転する

0 1 0 1 1 0 0 1
変更後のdata

1 0 1 0 0 1 1 0

(data&0x33)<<2 1 0
(data&0xCC)>>2

1 0
1 0

0 1

1 0 1 0 1 0 0 1
明日使えないすごいビット演算
●

ビット列を逆転する

0 1 0 1 1 0 0 1
1 0 1 0 0 1 1 0

1 0 1 0 1 0 0 1
明日使えないすごいビット演算
●

ビット列を逆転する

0 1 0 1 1 0 0 1
1 0 1 0 0 1 1 0
1 0 1 0 1 0 0 1
1 0 0 1 1 0 1 0
明日使えないすごいビット演算
●

ビット列を逆転する

0 1 0 1 1 0 0 1

1 0 0 1 1 0 1 0
明日使えないすごいビット演算
●

ビット列を逆転する

●

dataは32ビット符号なし型とする

data =
|
data =
|
data =
|
data =
|
data =

((data &
((data &
((data &
((data &
((data &
((data &
((data &
((data &
(data <<

0x55555555)
0xAA555555)
0x33333333)
0xCCCCCCCC)
0x0F0F0F0F)
0xF0F0F0F0)
0x00FF00FF)
0xFF00FF00)
16) | (data

<<
>>
<<
>>
<<
>>
<<
>>
>>

1)
1);
2)
2);
4)
4);
8)
8);
16);
明日使えないすごいビット演算
●

1になっているビットの数を数える

●

ビットレベルでハミング距離を取りたい時などに使う

●

素直な実装(int型を32bitと仮定)

int count = 0;
for (int i = 0;i < 32;i++) {
count += (data >> i) & 1;
}
明日使えないすごいビット演算
●

1になっているビットの数を数える

●

ちょっと速い実装

int count = 0;
for(; data; data &= data – 1) {
++count;
}
data &= data-1で1になっている一番小さい桁が0になる
明日使えないすごいビット演算
●

●

1になっているビットの数を数える
けっこう速い実装
10進数
2進数
1の個数
0
00000000 0
1
00000001 1
2
00000010 1
3
00000011 2
4
00000100 1
...
...
...
255
11111111 8
あらかじめ0~255までの数について1の個数を数えて配列に
入れておく
明日使えないすごいビット演算
●

1になっているビットの数を数える

●

けっこう速い実装

int count = 0;
count += table[data & 0xFF];
count += table[(data >> 8) & 0xFF];
count += table[(data >> 16) & 0xFF];
count += table[(data >> 24) & 0xFF];
table[256] : 1の個数が入った配列
明日使えないすごいビット演算
●

1になっているビットの数を数える

●

配列を使った実装はけっこう速い
–

素直な方法の20倍くらい
明日使えないすごいビット演算
●

1になっているビットの数を数える

●

配列を使った実装はけっこう速い
–

●

素直な方法の20倍くらい

しかし、さらに倍くらい速い実装が存在する
明日使えないすごいビット演算

1

0

1

1

0

1

0

0

各桁の0/1を「その桁の1の個数」と読み替えることができる
明日使えないすごいビット演算

1個 0個 1個 1個 0個 1個 0個 0個
各桁の0/1を「その桁の1の個数」と読み替えることができる
明日使えないすごいビット演算

1個 0個 1個 1個 0個 1個 0個 0個
0x55

0

1

0

1

0

1

0

1

ビット論理積

0個

1個

1個

0個
明日使えないすごいビット演算

1個 0個 1個 1個 0個 1個 0個 0個
0xAA

1

0

1

0

1

0

1

ビット論理積

1個

1個

0個

0個

0
明日使えないすごいビット演算

1個 0個 1個 1個 0個 1個 0個 0個
&0xAA 1個
&0x55

1個
0個

0個
1個

0個
1個

0個
明日使えないすごいビット演算

1個 0個 1個 1個 0個 1個 0個 0個
1個

1個

0個

0個

0個

1個

1個

0個
明日使えないすごいビット演算

1個 0個 1個 1個 0個 1個 0個 0個
1個

1個

0個

0個

0個

1個

1個

0個

足し算

0

1個

1

0個

0

1個

0

0個

2桁ごとに「その2桁にあった1の数」が格納された!!!
明日使えないすごいビット演算

1個 0個 1個 1個 0個 1個 0個 0個
0

1個

&0xCC 0

1個

0個

1

&0x33

1

0

0個
1個

0

0個

0
0

1個

0個
明日使えないすごいビット演算

1個 0個 1個 1個 0個 1個 0個 0個
0

1個

1

0個

1
0

0

1個

0

0個

0個

0

0個

1個

0

1個
明日使えないすごいビット演算

1個 0個 1個 1個 0個 1個 0個 0個
0

1個

1

0個

1
0

0

1個

0

0個

0個

0

0個

1個

0

1個

0

1個

足し算

0

0

1

1個

0

0
明日使えないすごいビット演算

1個 0個 1個 1個 0個 1個 0個 0個
0

0

1

1個

&0xF0 0

0

1

1個

0

0

1個

0

&0x0F

0

0

0

1個
明日使えないすごいビット演算

1個 0個 1個 1個 0個 1個 0個 0個
0

0

1

1個

0

0

0

1個

0

0

0

1個

0

0

1

1個
明日使えないすごいビット演算

1個 0個 1個 1個 0個 1個 0個 0個
0

0

1

1個

0

0

0

1個

0

0

0

1個

0

0

1

1個

0

0個

足し算

0

0

0

0

0

1
明日使えないすごいビット演算
●

1になっているビットの数を数える

●

かなり速い実装(dataはunsigned int型)

data =
+
data =
+
data =
+
data =
+
data =
+

(data & 0x55555555)
((data & 0xAAAAAAAA)
(data & 0x33333333)
((data & 0xCCCCCCCC)
(data & 0x0F0F0F0F)
((data & 0xF0F0F0F0)
(data & 0x00FF00FF)
((data & 0xFF00FF00)
(data & 0x0000FFFF)
((data & 0xFFFF0000)

>> 1);
>> 2);
>> 4);
>> 8);
>> 16);
明日使えないすごいビット演算
●

こうして、苦労の末我々は爆速で1になっているビットの数を数
えるアルゴリズムを手に入れた!!!
明日使えないすごいビット演算
●

●

こうして、苦労の末我々は爆速で1になっているビットの数を数
えるアルゴリズムを手に入れた!!!
しかし・・・
明日使えないすごいビット演算
●

●

●

こうして、苦労の末我々は爆速で1になっているビットの数を数
えるアルゴリズムを手に入れた!!!
しかし・・・
IntelのSIMD拡張命令セット、SSE4.2から、ズバリ「1になって
いるビットの数を数える」CPU命令が追加された!(popcnt)
明日使えないすごいビット演算
●

●

●

こうして、苦労の末我々は爆速で1になっているビットの数を数
えるアルゴリズムを手に入れた!!!
しかし・・・
IntelのSIMD拡張命令セット、SSE4.2から、ズバリ「1になって
いるビットの数を数える」CPU命令が追加された!(popcnt)
–

実際ビット演算を使ったアルゴリズムより2倍ほど速い
明日使えないすごいビット演算
●

●

●

こうして、苦労の末我々は爆速で1になっているビットの数を数
えるアルゴリズムを手に入れた!!!
しかし・・・
IntelのSIMD拡張命令セット、SSE4.2から、ズバリ「1になって
いるビットの数を数える」CPU命令が追加された!(popcnt)
–

●

実際ビット演算を使ったアルゴリズムより2倍ほど速い

我々の努力は無駄だった!!!!!
まとめと注意

●
●

ビット演算はうまく使うととても高速
ぱっと見何してるか判りづらいのでバグを埋め込
みやすい
–

ものすごい高速化をする必要のないときは使わ
ないほうが吉
まとめと注意

●
●

ビット演算はうまく使うととても高速
ぱっと見何してるか判りづらいのでバグを埋め込
みやすい
ものすごい高速化をする必要のないときは使わ
ないほうが吉
CPU命令速い!!!!!
–

●

–

本当に高速化したいときはまずこっちを考えるべき
おわり

More Related Content

PDF
プログラミングコンテストでの動的計画法
PDF
プログラムを高速化する話
PDF
ウェーブレット木の世界
PDF
プログラミングコンテストでのデータ構造 2 ~動的木編~
PDF
最小カットを使って「燃やす埋める問題」を解く
プログラミングコンテストでの動的計画法
プログラムを高速化する話
ウェーブレット木の世界
プログラミングコンテストでのデータ構造 2 ~動的木編~
最小カットを使って「燃やす埋める問題」を解く

What's hot (20)

PDF
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
PDF
RSA暗号運用でやってはいけない n のこと #ssmjp
PDF
中3女子でもわかる constexpr
PPTX
充足可能性問題のいろいろ
PDF
指数時間アルゴリズム入門
PDF
マルチコアを用いた画像処理
PDF
Union find(素集合データ構造)
PDF
何となく勉強した気分になれるパーサ入門
PDF
様々な全域木問題
PDF
Constexpr 中3女子テクニック
PDF
プログラミングコンテストでの乱択アルゴリズム
PDF
高速な倍精度指数関数expの実装
PDF
LLVM最適化のこつ
PDF
CRC-32
PDF
双対性
PDF
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
PDF
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
PDF
直交領域探索
PDF
Rolling Hashを殺す話
PDF
条件分岐とcmovとmaxps
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
RSA暗号運用でやってはいけない n のこと #ssmjp
中3女子でもわかる constexpr
充足可能性問題のいろいろ
指数時間アルゴリズム入門
マルチコアを用いた画像処理
Union find(素集合データ構造)
何となく勉強した気分になれるパーサ入門
様々な全域木問題
Constexpr 中3女子テクニック
プログラミングコンテストでの乱択アルゴリズム
高速な倍精度指数関数expの実装
LLVM最適化のこつ
CRC-32
双対性
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
直交領域探索
Rolling Hashを殺す話
条件分岐とcmovとmaxps
Ad

Viewers also liked (15)

PDF
ドット絵でプログラミング!難解言語『Piet』勉強会
PDF
Vivado hls勉強会5(axi4 stream)
PDF
Vivado hls勉強会1(基礎編)
PDF
GPUが100倍速いという神話をぶち殺せたらいいな ver.2013
PDF
AAをつくろう!
PDF
Word2vecで大谷翔平の二刀流論争に終止符を打つ!
PDF
Data Science Bowl 2017 Winning Solutions Survey
PDF
High performance python computing for data science
PPT
30分で博士号がとれる画像処理講座
PDF
NIPS2016論文紹介 Riemannian SVRG fast stochastic optimization on riemannian manif...
PDF
Quoraコンペ参加記録
PDF
Icml2015 論文紹介 sparse_subspace_clustering_with_missing_entries
PDF
Scikit learnで学ぶ機械学習入門
PDF
IIBMP2016 深層生成モデルによる表現学習
PPTX
猫でも分かるVariational AutoEncoder
ドット絵でプログラミング!難解言語『Piet』勉強会
Vivado hls勉強会5(axi4 stream)
Vivado hls勉強会1(基礎編)
GPUが100倍速いという神話をぶち殺せたらいいな ver.2013
AAをつくろう!
Word2vecで大谷翔平の二刀流論争に終止符を打つ!
Data Science Bowl 2017 Winning Solutions Survey
High performance python computing for data science
30分で博士号がとれる画像処理講座
NIPS2016論文紹介 Riemannian SVRG fast stochastic optimization on riemannian manif...
Quoraコンペ参加記録
Icml2015 論文紹介 sparse_subspace_clustering_with_missing_entries
Scikit learnで学ぶ機械学習入門
IIBMP2016 深層生成モデルによる表現学習
猫でも分かるVariational AutoEncoder
Ad

Similar to 明日使えないすごいビット演算 (20)

PDF
Javaセキュアコーディングセミナー東京第2回講義
PDF
kagami_comput2015_2
PDF
kagami_comput2016_02
PDF
kagamicomput201802
PDF
kagamicomput201702
PPT
計算機理論入門03
PPTX
SIMDで整数除算
PDF
Deflate
PDF
フラグを愛でる
PDF
コンピューターの1+1
PDF
kagami_comput2015_3
PDF
kagami_comput2016_03
PDF
Haswellサーベイと有限体クラスの紹介
PDF
Pyramid
PPTX
Schönhage Strassen Algorithm
PDF
実行時のデータ型の表現手法
PDF
kagamicomput201703
PPTX
PHP でバイナリ変換プログラミング
PPTX
T77 episteme
PDF
教育ガラパゴスは必要ですか?
Javaセキュアコーディングセミナー東京第2回講義
kagami_comput2015_2
kagami_comput2016_02
kagamicomput201802
kagamicomput201702
計算機理論入門03
SIMDで整数除算
Deflate
フラグを愛でる
コンピューターの1+1
kagami_comput2015_3
kagami_comput2016_03
Haswellサーベイと有限体クラスの紹介
Pyramid
Schönhage Strassen Algorithm
実行時のデータ型の表現手法
kagamicomput201703
PHP でバイナリ変換プログラミング
T77 episteme
教育ガラパゴスは必要ですか?

More from 京大 マイコンクラブ (20)

PDF
テキストファイルを読む💪 第1回
PDF
かわいくなろうとしたら語彙力が下がった話
PDF
Common Lisp入門
PDF
多倍長整数の乗算と高速フーリエ変換
PDF
つくってあそぼ ラムダ計算インタプリタ
PDF
Geometry with Unity
PDF
セミコロンレスc++
PDF
エンジニアと健康
PPTX
女の子になれなかった人のために
PDF
Pietで競プロしよう
ODP
もし太陽のコアがIntelCoreだったら
PDF
C# ゲームプログラミングはホントにメモリのことに無頓着でいいの?
PDF
プログラムを高速化する話Ⅱ 〜GPGPU編〜
PDF
No SSH (@nojima; KMC関東例会)
PDF
DTM練習会2017第1.5回 「伴奏の付け方」
PPTX
hideya流 テストプレイ観察術
PDF
暗号技術入門 秘密の国のアリス 総集編
PDF
C#でゲームを作る2016 第8回
PDF
C#でゲームを作る2016 第7回
テキストファイルを読む💪 第1回
かわいくなろうとしたら語彙力が下がった話
Common Lisp入門
多倍長整数の乗算と高速フーリエ変換
つくってあそぼ ラムダ計算インタプリタ
Geometry with Unity
セミコロンレスc++
エンジニアと健康
女の子になれなかった人のために
Pietで競プロしよう
もし太陽のコアがIntelCoreだったら
C# ゲームプログラミングはホントにメモリのことに無頓着でいいの?
プログラムを高速化する話Ⅱ 〜GPGPU編〜
No SSH (@nojima; KMC関東例会)
DTM練習会2017第1.5回 「伴奏の付け方」
hideya流 テストプレイ観察術
暗号技術入門 秘密の国のアリス 総集編
C#でゲームを作る2016 第8回
C#でゲームを作る2016 第7回

明日使えないすごいビット演算