ビット演算 | やさしい基礎理論
この連載は、基本情報技術者試験の受験者を対象としたものです。
多くの受験者が苦手としている「情報の基礎理論」の分野から毎回1つずつテーマをあげて、やさしくポイント解説と問題解説を行います。苦手分野を克服して、試験の得点をアップしましょう。
今回のテーマは、 ビット演算 です。
ビット単位の論理演算
ビット演算は、データを2進数で表して演算するものです。
ビット演算には、「ビット単位の論理演算」と「ビット単位のシフト演算」があります。
ビットは、「2進数の桁」という意味です。ビット単位の論理演算は、2つの2進数のデータで桁ごとに論理演算を行います。
ビット単位のシフト演算は、2進数のデータを指定した桁数だけずらします。
図1に、ビット単位の論理演算の例を示します。
ビット単位の論理演算は、特定の桁だけを覆い隠す(マスクする)ように変化させる演算なので、「マスク演算」とも呼ばれます。
ここでは、マスクされるデータを「データ」、特定の桁を指定するデータを「マスク」で示しています。
(1)AND演算
01010101 データ
AND 00001111 マスク
―――――――――――――
00000101 演算結果
※マスクで0になっている桁が0になり、マスクで1になっている桁は変化しない。
(2)OR演算
01010101 データ
OR 00001111 マスク
―――――――――――――
01011111 演算結果
※マスクで0になっている桁は変化せず、マスクで1になっている桁が1になる。
(3)XOR演算
01010101 データ
XOR 00001111 マスク
―――――――――――――
01011010 演算結果
※マスクで0になっている桁は変化せず、マスクで1になっている桁が反転する。
ビット単位のAND演算の結果は以下の通りです。
0 AND 0 = 0、0 AND 1 = 0、1 AND 0 = 0、1 AND 1 = 1
したがって、マスクで0になっている桁が0になり、マスクで1になっている桁は変化しません。
ここでは、マスクが00001111なので、データの上位4桁がすべて0になり、下位4桁は変化しません。
このように、ビット単位のAND演算は、データの特定の桁だけをすべて0にして、残りの桁を変化させない場合に使われます。
ビット単位のOR演算の結果は以下の通りです。
0 OR 0 = 0、0 OR 1 = 1、1 OR 0 = 1、1 OR 1 = 1
したがって、マスクで0になっている桁は変化せず、マスクで1になっている桁が1になります。
ここでは、マスクが00001111なので、データの上位4桁は変化せず、下位4桁がすべて1になります。
このように、ビット単位のOR演算は、データの特定の桁だけをすべて1にして、残りの桁を変化させない場合に使われます。
ビット単位のXOR演算の結果は以下の通りです。
0 XOR 0 = 0、0 XOR 1 = 1、1 XOR 0 = 1、1 XOR 1 = 0
したがって、マスクで0になっている桁は変化せず、マスクで1になっている桁が反転(0が1になり、1が0になること)します。
ここでは、マスクが00001111なので、データの上位4桁は変化せず、下位4桁が反転します。
このように、ビット単位のXOR演算は、データの特定の桁だけを反転して、残りの桁を変化させない場合に使われます。
ビット単位のシフト演算
ビット単位のシフト演算は、2進数のデータを指定した桁数だけずらします。
上位桁(左方向)にずらすことを「左シフト」と呼び、下位桁(右方向)にずらすことを「右シフト」と呼びます。
それぞれに「論理シフト」と「算術シフト」があり、「論理左シフト」「論理右シフト」および「算術左シフト」「算術右シフト」と呼びます。
シフトは、レジスタを使って行われます。
レジスタは、コンピュータの演算制御装置であるCPUの内部にあるデータ格納領域です。
CPUの種類によってレジスタのサイズは、決まっています。
たとえば、レジスタのサイズが8ビットなら、左シフトで上位桁からはみ出した数値は失われ、右シフトで下位桁からはみ出した数値は失われます。
左シフトでは下位桁に空きができ、右シフトでは上位桁に空きができますが、ここに何を入れるかが、論理シフトと算術シフトで異なります。
論理シフトでは、左シフトで空いた下位桁には0を入れ、右シフトで空いた上位桁にも0を入れます。
図2に論理シフトの例を示します。
論理シフトは、単に桁をずらすために使われます。ここでは、シフト前とシフト後のデータを示しています。
レジスタのサイズは、8ビットだとします。
(1)1ビットの論理左シフト
00111100 シフト前
01111000 シフト後
※左シフトで空いた下位桁には0を入れる。
(2)1ビットの論理右シフト
00111100 シフト前
00011110 シフト後
※右シフトで空いた上位桁には0を入れる。
算術シフトは、左シフトで乗算を実現し、右シフトで除算を実現します。
2進数は、左に1桁シフトするごとに値が2倍になり、右に1桁シフトするごとに値が1/2になります。
これらで、2を掛ける乗算と2で割る除算を実現するのです。
その際に、2の補数表現(この連載の第2回で説明しています)を使ったマイナスの値でも、正しい乗算と除算の結果が得られるように、最上位桁の符号ビットをシフトの対象とせずに、左シフトで空いた下位桁には0を入れますが(これは論理シフトと同じです)、右シフトで空いた上位桁には符号ビットと同じ値(プラスの値なら0、マイナスの値なら1)を入れます。
こうすると、マイナスの値でも、正しい乗算と除算の結果が得られるのです。
図3に算術シフトの例を示します。
ここでも、シフト前とシフト後のデータを示しています。レジスタのサイズは、8ビットだとします。
(1)1ビットの算術左シフト(2を掛ける乗算)
11111100 シフト前(10進数でマイナス4)
11111000 シフト後(10進数でマイナス8)
※符号ビットをシフトの対象とせず、左シフトで空いた下位桁には0を入れる。
(2)1ビットの算術右シフト(2で割る除算)
11111100 シフト前(10進数でマイナス4)
11111110 シフト後(10進数でマイナス2)
※符号ビットをシフトの対象とせず、右シフトで空いた上位桁には符号ビットと同じ値(ここでは1)を入れる。
ビット演算に関する問題の例(その1)
ビット演算に関する問題を2つ紹介しましょう。
はじめは、ビット単位の論理演算の問題です。
問1(出典:H28秋問1)
8ビットのビット列の下位4ビットが変化しない操作はどれか。
ア 16進表記 0F のビット列との排他的論理和をとる。
イ 16進表記 0F のビット列との否定論理積をとる。
ウ 16進表記 0F のビット列との論理積をとる。
エ 16進表記 0F のビット列との論理和をとる。
問題では、0Fという16進数が使われています。
ビット演算は、データを2進数で表して演算するものなので、16進数の0Fを2進数に変換しましょう。
16進数は、16で桁上がりするので、1桁を0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、Fで表します。
A~Fは、10進数なら10~15です。16進数の1桁は、2進数の4桁になります。
2進数の4桁の重みは、上位桁から順に8、4、2、1なので、これらをどのように足し合わせれば16進数の1桁になるかを考えて変換します。
0は、8、4、2、1のどれも足さないので、すべての桁が0の0000です。
Fは10進数で15であり、15=8+4+2+1なので、すべての桁が1の1111です。
したがって、16進数の0Fは、2進数で00001111です。
この00001111をマスクとして、選択肢に示されたどの演算を行うと、下位4ビットが変化しないかを答えます。
選択にある排他的論理和、否定論理積、論理積、論理和は、XOR、NAND(NOT ANDという意味で、AND演算の結果をNOT演算します)、AND、ORの日本語名です。
00001111は、下位4ビットがすべて1です。
XOR演算では、1に対応する桁が反転します。
NAND演算では、AND演算で1に対応する桁が変化し、さらにNOT演算(すべての桁を反転する演算)するので、下位4ビットを含むすべての桁が反転します。
AND演算では、1に対応する桁が変化しません。
OR演算では、1に対応する桁がすべて1になります。
したがって、下位4ビットが変化しないのは、AND演算(論理積)であり、選択肢ウが正解です。
ビット演算に関する問題の例(その2)
次は、ビット単位のシフト演算の問題です。
問2(出典:H25秋問2)
32ビットのレジスタに16進数ABCDが入っているとき,2ビットだけ右に論理シフトしたときの値はどれか。
ア 2AF3 イ 6AF3 ウ AF34 エ EAF3
ここでもABCDという16進数が使われているので、2進数に変換してから、シフト演算しましょう。
A、B、C、Dは、10進数で10、11、12、13です。
10=8+0+2+0なので、1010です。
11=8+0+2+1なので、1011です。
12=8+4+0+0なので、1100です。
13は、8+4+0+1なので、1101です。
したがって、16進数のABCDは、2進数で1010101111001101です。
ここでは、32ビットのレジスタなので、32桁の2進数を保持でき、左シフトで上位桁からはみ出した数値と、右シフトで下位桁からはみ出した数値は消えてなくなります。
1010101111001101という32ビットのデータを2ビットシフトすると、下位2桁の01がはみ出し、空いた上位2桁に00が入って、0010101011110011になります。
選択肢が16進数になっているので、0010101011110011を16進数にしましょう。
2進数を下位桁から4ビットずつに区切って、0010、1010、1111、0011として、それぞれを16進数に変換します。
0010は、0+0+2+0=2です。
1010は、8+0+2+0=10なので16進数でAです。
1111は、1+1+1+1=15なので16進数でFです。
0011は、0+0+1+1=3です。
したがって、0010101011110011は、16進数で2AF3であり、選択肢アが正解です。
基本情報技術者試験の公開問題を見ると、過去に出題された問題の再利用が多いことがわかります。
したがって、試験に合格するために最も効率的で効果的な学習方法は、過去問題を数多く解き、できなかった問題があれば、できるようになるまで練習することです。
もしも、今回取り上げた問題がすぐにできなかったら、できるようになるまで練習してください。
それでは、またお会いしましょう!
label 関連タグ免除試験を受けた 74.9% の方が、 科目A免除資格を得ています。
『プログラムはなぜ動くのか』(日経BP)が大ベストセラー
IT技術を楽しく・分かりやすく教える“自称ソフトウェア芸人”
大手電気メーカーでPCの製造、ソフトハウスでプログラマを経験。独立後、現在はアプリケーションの開発と販売に従事。その傍ら、書籍・雑誌の執筆、またセミナー講師として活躍。軽快な口調で、知識0ベースのITエンジニアや一般書店フェアなどの一般的なPCユーザの講習ではダントツの評価。
お客様の満足を何よりも大切にし、わかりやすい、のせるのが上手い自称ソフトウェア芸人。
主な著作物
- 「プログラムはなぜ動くのか」(日経BP)
- 「コンピュータはなぜ動くのか」(日経BP)
- 「出るとこだけ! 基本情報技術者」 (翔泳社)
- 「ベテランが丁寧に教えてくれる ハードウェアの知識と実務」(翔泳社)
- 「ifとelseの思考術」(ソフトバンククリエイティブ) など多数