ビット演算解説

Last-modified: 2023-04-16 (日) 16:57:45

ここでは回路ネットワークの算術回路におけるビット演算について解説する。
※回路についての基本的な理解がある事を前提にしています。

2023/02/02更新 「応用:ランプで数字を表示する」追加

ページ案内
基本詳細仕様と応用例ビット演算詳細

導入

ビット演算は便利なもので、シグナル1つで複数の装置を個別にオンオフすることも出来る。

例えば、ケーブルを繋いだベルトA,B,C,Dを制御するとき、シグナルをA~Dまで用意しなくて済む。

bit_1.jpg

解説の前に、これを制御シグナルSのみ、ビット演算なしで制御する方法を考えてみよう。

 
ベルトA:S = 1
ベルトB:S = 2
ベルトC:S = 3
ベルトD:S = 4
 

これでは1つしか動かせないので、条件を変えてみる。

 
ベルトA:S >= 1
ベルトB:S >= 2
ベルトC:S >= 3
ベルトD:S >= 4
 

これも組み合わせが限定され、Dのみ動かす等が出来ない。

室内灯のスイッチのように、個別に付けたり消したり出来れば…
そういった場合にビットが活躍する。

 

ビットとは

ビットとは、1つのON/OFFスイッチに置き換えて考えられる情報の単位である。

1ビットとはON/OFFスイッチが1つあるということだ。

ON/OFFは1と0で表される。

 
ONなら  … 1
OFFなら … 0
 

Factorioで考えた場合、1ビット分の情報(=1もしくは0)があれば1つの装置をON/OFF出来る。

導入の例のように、4つの装置を個別でON/OFFするには4ビット分の情報が必要になる。
4ビットとはON/OFFスイッチが4つなので、以下のようになる。

 
全てONなら  … 1111
全てOFFなら … 0000
 

これは、2進法で表した4桁の数値として扱うことが出来る。
※2進法 … 1よりも大きい数になると次の桁に繰り上がる記数法

4ビットで表現可能な情報の数は、4つのON/OFFスイッチの状態の組み合わせの数に等しい。

 
2進数0000000100100011010001010110011110001001101010111100110111101111
10進数0123456789101112131415

※nビット = 2のn乗通り、4ビットでは2*2*2*2 = 16通り
 2進数を10進数に直した数値xは、ON/OFFスイッチの組み合わせのx番目と言える

 

導入の例で言えば、ベルトA,B,C,Dに対して制御シグナルSの(2進数における)1~4桁目を割り当てればよい。
しかし、以下のような設定は適切ではない。

 
ベルトA:S = 1
ベルトB:S = 10
ベルトC:S = 100
ベルトD:S = 1000
 

Factorioは数字を全て10進数として扱うため、2進数の値は以下のように10進数に直す必要がある。

 
ベルトA:S = 1
ベルトB:S = 2
ベルトC:S = 4
ベルトD:S = 8
 

さらに、制御シグナルSのどの桁がONなのかを判別するために、算術回路のビット演算であるANDを用いる。

 

ビット演算とは

ビット演算とは、いわば並んだON/OFFスイッチ(=ビット)をいっぺんに操作できる演算のことだ。

Factorioでは算術回路に以下のビット演算子が用意されている。

 
<<,>>,AND,OR,XOR
 

<<,>>(左シフト,右シフト)

ビットを左か右にずらす。Factorioでは10進数で指定した桁の数だけずれる。

2進数(指定数は10進数)10進数備考
0001 << 3 = 10001 << 3 = 8<< 3 なので3桁左にずれる
1000 >> 2 = 00108 >> 2 = 2>> 2 なので2桁右にずれる
0010 >> 2 = 00002 >> 2 = 0>> 2 なので2桁右にずれ、はみ出した1は消える
0011 << 1 = 01103 << 1 = 6<< 1 なので1桁左にずれる、1が複数でもそのまま移動される
 

AND(論理積)

ANDの左右のビットにおいて、どちらともONのビットを出力する。

2進数10進数
0101 AND 0011 = 00015 AND 3 = 1

備考:0101に対し、AND 0011は1,2桁目が同じくONである桁のみONにするので1桁目だけがONとなる

 

OR(論理和)

ORの左右のビットにおいて、どちらかがONのビットを出力する。

2進数10進数
0101 OR 0011 = 01115 OR 3 = 7

備考:0101は1,3桁目がON、OR 0011は1,2桁目がONであるため、1,2,3桁目がONとなる

 

XOR(排他的論理和)

XORの左右のビットにおいて、ONかOFFで一致するビットはOFF、異なるビットはONを出力する。

2進数10進数
0101 XOR 0011 = 01105 XOR 3 = 6

備考:0101とXOR 0011では、1,4桁目はONかOFFで一致しているのでOFF、2,3桁目はONとOFFで異なるのでONとなる

 

ビット演算を用いた個別制御

ビット演算を用い、制御シグナルSのみでベルトA,B,C,Dを制御する設定は以下の通り。

 
算術回路1:S AND 1 = S → ベルトA:S = 1
算術回路2:S AND 2 = S → ベルトB:S = 2
算術回路3:S AND 4 = S → ベルトC:S = 4
算術回路4:S AND 8 = S → ベルトD:S = 8
 

ANDで各桁のON/OFFを検出している。以下のように2進数にすると分かりやすい。

 
算術回路1:S AND 0001 = S → ベルトA:S = 0001
算術回路2:S AND 0010 = S → ベルトB:S = 0010
算術回路3:S AND 0100 = S → ベルトC:S = 0100
算術回路4:S AND 1000 = S → ベルトD:S = 1000
 

Sの出力設定例は以下の通り。

 
条件回路1:任意の条件 出力S(1) → 算術回路A:S << 0 = S ─┬→ ANDの算術回路
条件回路2:  〃     〃  → 算術回路B:S << 1 = S ─┤
条件回路3:  〃     〃  → 算術回路C:S << 2 = S ─┤
条件回路4:  〃     〃  → 算術回路D:S << 3 = S ─┘
 

左シフトで制御するビットの桁を変えて条件回路1~4を上記のベルトA~Dに対応させている。

 

1つの装置に複数の条件を設定したい場合は、追加条件の出力のみ別のシグナルとORを使う。

bit_2.jpg

ORを使わず、図の条件2~4の出力をまとめて条件回路に繋ぐことでも同じ動作が出来る。

条件2~4の出力 → 条件回路:S > 0 出力S(1) → 算術回路:S << 1 = S → ANDの算術回路
 

応用:ランプで数字を表示する

bit_disp_1.jpg

2016年2月25日はFactorioがSteamで早期アクセスとしてリリースされた日である

 

この項ではランプとビット演算を用いて、アラビア数字を表示する7セグメントディスプレイの実装方法を説明する。
用いるのはランプのほか算術回路1つ、定数回路1つと非常にコンパクトになっている。

※参考リンク
wikipedia - 7セグメントディスプレイ
Simplest 7-segment display possible - 0-9 displayed with one arithmetic and one constant combinator

 

概要

この実装では信号の値の最上位のビットによってランプを制御する方法を用いる。

Factorioの信号の値は32ビット符号付き整数であり、最上位のビットによって値の正負が分かれている。

 
10進数2進数
21474836470111 1111 1111 1111 1111 1111 1111 1111
-21474836481000 0000 0000 0000 0000 0000 0000 0000
 

ランプの条件:信号 < 0 とすると以下のようになる。

値が0以上 → 最上位ビットが0、ランプは点灯しない
値が0よりも小さい → 最上位ビットが1、ランプは点灯する

次に、7セグメント分の信号の上位ビットから順に作動条件を10ビット分(=0~9)2進数で埋め込む。
あとは信号を左シフトする数により、どのビットを最上位ビットとするかを制御すればよい。

 

実装例

bit_disp_2.jpg

概略図

定数回路にセグメントにあたる信号A~Gを以下の通り設定し、算術回路に接続する。

 
信号32ビットバイナリ(2進数)32ビット符号付き整数
A1011 0111 1100 0000 0000 0000 0000 0000-1212153856
B1000 1110 1100 0000 0000 0000 0000 0000-1900019712
C1111 1001 1100 0000 0000 0000 0000 0000-104857600
D0011 1110 1100 0000 0000 0000 0000 00001052770304
E1010 0010 1000 0000 0000 0000 0000 0000-1568669696
F1101 1111 1100 0000 0000 0000 0000 0000-541065216
G1011 0110 1100 0000 0000 0000 0000 0000-1228931072
 

算術回路はEach(黄*)<< X 出力:Eachとし、出力を全てのランプに接続する。

ランプの設定は、概略図のように各位置に対応する信号に対して0未満で作動とする。

算術回路に信号X(値:0~9)を入力すると、数字に対応してランプが点灯する。

セグメントを増やすには、信号の種類を増やし、同じように2進数で作動条件を決め、10進数で定数回路に出力させればよい。

 

※2進数の変換に便利なサイト
2,8,10,16進数 計算・変換(マイナス、小数点対応)

 
bit_disp_3.jpg
建築計画コード:7 segment display

0eNrdmG1rqzAUx7/KyGs7kmgSlb65d09fYXApxdpsC/hEjOOW4ne/id3UumatgoNehNJo8s/JL+ecPOzBJql4IUWmQLgHIs6zEoR/9qAUr1mUmHdqV3AQAqF4ChyQRakplWmUJIskSgtQO0BkW/4XhKh2zjaMpFBvKVciXsR5uhFZpHLZ08D1ygE8U0IJfrCkKezWWZVuuNSdnLLBAUVe6iZ5ZjrWMgsEA++WOGCn/3s+vSW6Cz04JfNkveFv0bvQ3eq6sZBxJdRaf9u2Ai9Clmr9ZSTvQqpKv+ksaGosfoODeKkigxGaQlpEshlaCJbmc1Vy3UeSSz0oJSt+aJHx2PRZmk6Q+XmVnGf9YYstCF3DtVcm9aque+8+0eCL0eAODZsVza8fRuNZ0LgXo3H/FzRogAZb0HgXo0E/FVB3M6PBAzS+BQ2ZkmvIVeeaodcwCxo6Jdd4s6K5nxkNG6BBtohiU5LNdbOhX5ao43JgQeVPST7kqpOPbYkKpiQbd1YUDz8dUdDCBsEpcPBVwwmGcFwbHDQliOaF8zj3MmXLvQhPgeFeNYxh8kXIBmfSNhjNCudpbk+BQzq2BIy8KXuaK6czPEAhPbBPw787NSBy5kh/2qs+qLGgobYV8mBls588xbDT7jCWEzjyKH4zrEpuZC5v92wa5QXXwBszwXKp6+SVKqrRvdejJoZq8A7A9gpWN+625p+Oc3ZeYOvPF8/Mi0gUl5bLojNn3sr48gJh/RDXJ/TMDdKZs9CHWgAhRAEzC0B7lzRG7e5IDeptJqMQtmLuKLH7nhiCBDMGXei1Yt4osYcjywj1KQ3006qRUWqPfTXiIUgJRp0YHSX2dDyh2A9cBFk3BWyU2nNPLWg1/CYSLo+cQQY7LIYr53ARGfYuPB2QRBuuDQPspuSvqRa52YqySKKd/vauvbsJAOwjHRaYUUp86vt1/Q9fCCYl