みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

シフト演算について

基本情報技術者試験の資格試験のための勉強をしているものです。

現在、カテゴリー的には基礎理論の離散数学、
シフト演算のうち、「論理シフト」ではなく、
「算術シフト」で理解できない点があります。

左シフトは理解できたつもりなんですが・・・
右シフトがいまいちよくわかりません。
以下に例題を表記します。

【10001100を2ビット左シフト】
先頭ビットは符号ビットということで、マイナスの数値になるのだと思います。すると、

【元の数】
10001100
=-(0001100)
=-(8+4)
=-12

【2桁左シフト結果=元の数×2^2】
10110000
=-(0110000)
=-(32+16)
=-48

となり、
元の数=-12
結果 =-48
で、結果が元の数×2^2で結果が合っているようです。
(と思っているだけなんですが)
元の数の考え方自体に間違いがありそうですが・・・
とりあえず進みます。

同様に
【10001100を2ビット右シフト】すると

【2桁右シフト結果=元の数×2^-2(=元の数×1/4)】
11100011
=-(1100011)
=-(64+32+8+4)
=-99

となり、
元の数=-12
結果 =-99
で、結果が元の数×2^-2(=元の数×1/4)と結果が合いません。

先頭符号を空いたビットに移動した部分は数えないのでしょうか。
すると、
元の値 =-12
結果  =-3
で結果が合う気がします。

過去の回答や検索サイトなどで調べてみましたがピンときません。
テキストにも、10進数での数値表記はなく、
答え合わせができなくて困っております。
どなたかお答えいただけると助かります。
どこが間違っているのか混乱しております。

先頭ビットが正負の符号ビットという前提の例題なのですが、
マイナス符号がついている前提となるので
先頭ビットや空いたビットに入れた符号ビットも含めて
「2の補数」で考える必要があるのかどうかも
よくわからなくなってきました。

つまり、元の数値「10001100」は「-12」ではなく
-(01110100)
=-(64+32+16+4)
=-116
なのでしょうか

なお、C言語は今のところ学習していないので、
C言語にまつわるご回答ですともっとわからなくなりそうです。

単純に間違いを指摘していただけると大変助かります。
よろしくお願いします。

投稿日時 - 2009-12-30 01:40:39

QNo.5556315

すぐに回答ほしいです

質問者が選んだベストアンサー

#1です。

おっしゃる通り、右シフトの時に符号ビットをそのままシフトするのは、
補数を使っているからです。
補数の場合は、ビットが反転している為、マイナスを表すときは、1が0になります。
理屈で言えば、右シフト(2分の1、4分の1、...)するのに桁の大きいところには
0が入るはずですので、符号ビットが1の時(負の時)には1を入れます。

ただ、今回の補足の例で左シフトの計算が合わないのは、桁数が足りないからです。
8桁の2の補数で表すことのできる範囲は-128~127です。
今回の場合、元の数が-116ですので、左に2ビットシフト(4倍)すると、
-464ですので2ビット足りません。
それで、本来立っていたビット(2桁目と3桁目)があふれてしまった為に
計算が合わなくなりました。

ためしに、10桁(1110001100)で同様の計算をすればうまくいくはずです。

投稿日時 - 2009-12-30 13:07:06

お礼

seiiiichiさん、ありがとうございました!

大変参考になり、理由がわかりました。
そして、左シフトも桁を足して補数での計算してみて、
答えも合いました!
いやあ、うれしいです。

「あふれ」、学んだはずなんですが。
慣れるために何度も復習したいと思います。
ありがとうございました。
頑張ります。

投稿日時 - 2009-12-30 14:09:36

このQ&Aは役に立ちましたか?

4人が「このQ&Aが役に立った」と投票しています

回答(2)

ANo.1

確かに、これだけだと、2の補数表現なのか、ただ単に第一ビットが
符号をあらわしているだけなのかよくわかりませんが、とりあえず
後者として話しを進めます。

論理シフトは符号ビットもシフトしますが、
算術シフトは符号ビットはシフトしませんし、シフトされません。

したがって、
【10001100を2ビット右シフト】
→ 10000011 (-3)

となり、計算は合います。

なので、質問者様の間違いは「符号ビットもシフトしてしまったこと」です。

投稿日時 - 2009-12-30 10:17:18

補足

さっそくのご回答、本当にありがとうございます。
ご回答いただいた方法ですと、スッキリします。
ありがとうございました!
今は単純にそのように理解していこうと思います。

ちなみになんですが、テキスト上では
「シフト演算」の「算術シフト」の「右シフト」は
空いたビットには「符号ビットと同じものを入れる。」
と書かれております。

今回の例では間違いのもととなったところですが、
10001100を算術シフトすると
2桁右シフトすると11100011となり(空いた所に符号ビットを入れる)
2桁左シフトすると10110000となる(空いた所に0を入れる)
とテキスト上はなっております。

左シフトと右シフトで、元の数値も結果の数値もどちらも
2の補数表現としてとらえて自分で検算的に
計算すると、今度は右シフトは答えが合うのですが、
左シフトで答えが合いません。

ご回答者様の方法でせっかく答えが合うのに、
「右シフトのときは符号ビットで埋める」という概念自体が
存在する意味がないような気がするのですが。

もしかして、

負の数の左シフトのときは「2の補数」の概念を使わず
先頭ビットは符号ビットとして考えて、後のビットをまんま計算する。

負の数の右シフトのときは全ビットを数値と考えて負の数と捉え
「2の補数」の概念で計算する。
という考え方もできるのでしょうか?

なにか考え方で欠けていそうなところなど
もしお分かりでしたら教えてください。

たしかにテキストには「2の補数」表現なのか
符号を表しているだけなのかは書かれておらず、
左シフトと右シフトも続けて書かれていますが
どちらがどちらの表現なのかなどは書かれていないので
何とも言えません^^
テキスト的には、大まかな概念を説明しただけで
それ以上は突っ込むなというところなのかもしれませんが
もやもやが晴れたらうれしいです。
よろしくお願いします。

投稿日時 - 2009-12-30 11:46:52

あなたにオススメの質問