人工知性を作りたい

私が日々、挑戦したことや学んだことなどを紹介していく雑記ブログです。 (新しいAI技術HTM, 専門の音声信号処理, 趣味のアニメ等も書いてます。)

global navigation menu page top

論理シフトと算術シフト!【Pythonで基本情報技術者になろう!】

f:id:hiro-htm877:20190619230445j:plain



 

f:id:hiro-htm877:20190601202549p:plain

 

 

 

  

 

 

基本情報技術者を目指す皆様へ】

・今回は2進数の論理シフトと算術シフトについて教えます!

・実際にPythonで計算を行い、疑問の解決につなげます。

 

コードが知りたい方は目次のソースコードへ飛んでください!

本記事のテーマ

Python基本情報技術者になろう!】

・論理シフトと算術シフト

説明

 

まず、

2進数のbit列を左もしくは右にずらす操作をシフト演算と呼びます

 

10進数に対して「10倍」、「1/10倍」するのはどういうことか、

例:230

230 * 10 =2300 ←10進数を左にずらしています

230 /   10 =23   ←10進数を右にずらしています

 

つまり、2進数における左シフトは「2倍」、右シフトは「1/2倍」されることになります。

コンピュータではこのシフト演算を用いてかけ算、わり算を実現しています。

 

このシフト演算は二つあり、

・符号を考慮しない:「論理シフト」

・符号を考慮した :「算術シフト」

一つずつ説明していきます

 

論理シフト

論理シフトとは、符号を考慮しないシフト操作です。

ここでのコンピュータは8bitとします。

左シフト(かけ算)

例:00010110(22)←カッコ内は10進数表記

3ビット左シフトさせると

   00010110(22)

00010110←←←(??)

こうなります。この空いたところは'0'で埋められ、はみ出たビットは削除されます

結果、

10110000(176)

となります。

先ほど左に1bitシフトは2倍と言いました。なので左に3bitシフトするということは

2倍×2倍×2倍=8倍することになります。

ここで、先ほどの左シフトの計算を見てみますと、

22 << 3 = 22×8 = 176(<<は左シフトの演算子

きちんと、2の3乗されていることがわかります。

 

右シフト(わり算)

例:01110000(112)←カッコ内は10進数表記

3ビット右シフトさせると

01110000   (112)

→→→01110000(???)

こうなります。この空いたところは'0'で埋められ、はみ出たビットは削除されます

結果、

00001110(14)

となります。

先ほど右に1bitシフトは1/2倍と言いました。なので右に3bitシフトするということは

1/2倍×1/2倍×1/2倍=1/8倍することになります。

ここで、先ほどの左シフトの計算を見てみますと、

112 >> 3 = 11×(1/8) = 14(>>は左シフトの演算子

きちんと、1/(2の3乗)されていることがわかります。

 

まとめ

・nビット左シフトは2のn乗倍

 →空いたところは'0'埋め

・nビット右シフトは(1/2)のn乗倍

 →空いたところは'0'埋め

 注意:今回は桁あふれを考慮しないためにシフトで削除するビットは'0'のみの8ビットを用いました。

算術シフト

 

算術シフトとは、符号を考慮したシフト操作です。

ここでのコンピュータは8bitとします。

左シフト(かけ算)

  ↓符号ビット(0:正、1:負)

例:11110110(ー128+118=−10)←カッコ内は10進数表記

2ビット左シフトさせると

   ↓ここは固定

   1|1110110(ー128+118=−10)

  11|10110←← (??)

こうなります。符号ビットは固定され、空いたところは'0'で埋められ、はみ出たビットは削除されます

結果、

11011000(ー128+88=−40)

となります。

左に3bitシフトするということは2倍×2倍=4倍することになります。

先ほどの左シフトの計算を見てみますと、

ー10 << 2 = ー10×4 = −40(<<は左シフトの演算子

きちんと、2の3乗されていることがわかります。

 

右シフト(わり算)

例:10111000(−128+56=−72)←カッコ内は10進数表記

3ビット右シフトさせると

↓ここは固定

10111000   (−128+56=−72)

1→→→0111000(???)

こうなります。符号ビットは固定、空いたところは'1'で埋められ、はみ出たビットは削除されます。

!!空いたところは'1'で埋めます。今までは0埋めだったので気をつけてください!

なぜ1で埋めるのかは10進数の計算と一緒に確認すればわかります。

 

結果、

11110111(ー128+119=ー9)

となります。

右に3bitシフトするということは1/2倍×1/2倍×1/2倍=1/8倍することになります。

先ほどの左シフトの計算を見てみますと、

−72 >> 3 = −72×(1/8) = −9(>>は左シフトの演算子

きちんと、1/(2の3乗)されていることがわかります。

 

まとめ

・nビット左シフトは2のn乗倍

 →空いたところは'0'埋め

・nビット右シフトは(1/2)のn乗倍

 →空いたところは'1'埋め 

 注意:今回は桁あふれを考慮しないためにシフトで削除するビットは

・左シフトの時は'1'

・右シフトの時は'0'

のみの8ビットを用いました。

 

以上で2進数の論理シフトと算術シフトの説明は終了です!

特に算術シフトは分かりにくいですが、「はみ出たビットは削除」と「空いたところは基本'0埋め'(算術シフトの右シフトだけ'1'埋め)」を覚えておきましょう!

 

最後にPythonで実際に2進数の論理シフトと算術シフトをしてみたいと思います!

Pythonで2進数の論理シフトと算術シフト

Code

if __name__ == "__main__" :
    # 論理シフトと算術シフト
    print("---"*5)
    print ("論理シフト")
    print("---"*5)
    print("・左3bitシフト")
    a = 0b00010110 # 22
    print (bin(a), "<< 3 =", bin(a<<3))
    print (a, "* 8 =", a<<3)

    print("・右3bitシフト")
    a = 0b01110000 # 112
    print (bin(a), ">> 3 =", bin(a>>3))
    print (a, "* 1/8 =", a>>3)
    print("")
    print("---"*5)
    print ("算術シフト")
    print("---"*5)
    print("・左3bitシフト")
    a =  0b1110110 # 118
    a =  0b0001001 # 反転
    a = ~a         # 符号付きに変換
    print(bin(a), a)
    print (bin(a), "<< 2 =", bin(a<<2))
    print (a, "* 4 =", a<<2)

    print("・右3bitシフト")
    a = 0b0111000 # 56
    a = 0b1000111 # 反転
    a = ~a        # 符号付きに変換
    print (bin(a), ">> 3 =", bin(a>>3))
    print (a, "* 1/8 =", a>>3))

 

出力

---------------
論理シフト
---------------
・左3bitシフト
0b10110 << 3 = 0b10110000
22 * 8 = 176
・右3bitシフト
0b1110000 >> 3 = 0b1110
112 * 1/8 = 14

---------------
算術シフト
---------------
・左3bitシフト
-0b1010 -10
-0b1010 << 2 = -0b101000
-10 * 4 = -40
・右3bitシフト
-0b1001000 >> 3 = -0b1001
-72 * 1/8 = -9

 

参考資料

・キタミ式イラストIT塾 基本情報技術者 平成31/01年