2進数のかけ算わり算の基礎
まず前提として、混乱してしまったので記述するのですが符号なしか符号ありによって
結果に違いがあります。
必ず符号があるかなしかは確認する必要があります。
2進数 | 符号なし | 符号あり |
---|---|---|
00000000 | 0 | 0 |
00000001 | 1 | 1 |
00000010 | 2 | 2 |
01111111 | 127 | 127 |
10000000 | 128 | -128 |
10000001 | 129 | -127 |
11111110 | 254 | -2 |
11111111 | 255 | -1 |
符号がついている場合は127を境に値が変化していきます。
符号ビットが0ならば正で1ならば負らしいです。
ややこしい
例題に入ります。
5510という10進数の数字があったとします
55100
// 上記は×10された数
551
// 上記は×1/10された数
110という2進数の数字があったとします
1100
// ×2された数
11
// ×1/2された数
上記のように2進数をあらわすビット列を、左もしくは右にずらす操作をシフト演算と呼びます。
論理シフト
シフト演算の中で、符号を考慮せずに行うシフト操作が論理シフトです。
符号を考慮しないの意味は「最上位のビットも含めて何も考えずにシフトする」ことです。
例えば8ビットで2進数を表わすデータがあるとします。
128 64 32 16 8 4 2 1
0 0 1 0 1 1 0 0
// 32 + 8 + 4 = 44
10進数だと44です。
左論理シフトを行います。左論理シフトは2n倍となります。
00101100
|00|101100
// 2ビット左にシフトさせると上部になる
その後にはみ出たビットは削除して開いたスペースに0で埋めます。
128 64 32 16 8 4 2 1
1 0 1 1 0 0 0 0
// 128 + 32 + 16 = 176
上記は44 * 2 * 2した2進数の数となります。
次は右論理シフトを行います。右論理シフトは1/2n倍となります。
00101100
001011|00|
右にはみ出たビットは削除します。
その後に空になったスペースを0で埋めます。
128 64 32 16 8 4 2 1
0 0 0 0 1 0 1 1
// 8 + 2 + 1 = 11
元の数値44 * 1/2 * 1/2倍した2進数が出来上がりました。
右や左にずらしたときに、はみ出た数字が1だった場合
左論理シフトではみ出た場合は、ビット数で表せる範囲を超えてしまったことになります。
その現象をオーバーフローと呼びます。
右論理シフトではみ出た数は割り算した結果の余りとなります。
算術シフト
符号を考慮して行うシフト演算が算術シフトです。
算術シフトでは、先頭の符号ビットを固定にして、それ以降のビットだけを左右にシフト操作します。
こちらでは符号を考慮します
符号を考慮するかしないかで大変混乱しました。
符号は8ビットの中の8ビット目の値です。
11100100
↑先頭の1が符号
64 32 16 8 4 2 1
1 1 0 0 1 0 0
// (+64) + (-32) + (-4) = 28
// 符号が1なので-28
左算術シフトは符号付きで2n倍
|1|1100100
|11|00100
はみ出たビットを削除して00100となります。
空になったスペースを0で埋めると
0010000
128 64 32 16 8 4 2 1
1 0 0 1 0 0 0 0
// (+128) + (-16)
// 符号付きなので-112
元の数値-28 * 2 * 2した2進数です。
右算術シフトは符号付きで1/2n倍となります。
11100100
|1| 11001|00|
// 先頭の1は固定
はみ出たビットは削除します。つまり00を削除です。
空になったスペースは符号ビットで埋めます
11111001
// 正の数(0)の場合は
00011001になります。
// 負の数(1)の場合は
11111001になります。
-28 * 1/2 * 1/2 で-7ですね。
まとめ
今回はシフト演算と少し割り算と掛け算をやりました。
ボリュームがあるので、次回でさらに割り算と掛け算を見てみます。