- ベストアンサー
シフト演算について
- 基本情報技術者試験の資格試験のための勉強をしているものです。シフト演算のうち、「論理シフト」ではなく、「算術シフト」で理解できない点があります。
- 左シフトは理解できたが、右シフトがよくわからない。例題では数値の右シフトを実行した結果が理解できない。
- 先頭ビットの符号ビットがマイナスの数値になることを考慮しながら、右シフトを実行すると結果が合わない。間違っている点を指摘してほしい。C言語については学習していない。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
#1です。 おっしゃる通り、右シフトの時に符号ビットをそのままシフトするのは、 補数を使っているからです。 補数の場合は、ビットが反転している為、マイナスを表すときは、1が0になります。 理屈で言えば、右シフト(2分の1、4分の1、...)するのに桁の大きいところには 0が入るはずですので、符号ビットが1の時(負の時)には1を入れます。 ただ、今回の補足の例で左シフトの計算が合わないのは、桁数が足りないからです。 8桁の2の補数で表すことのできる範囲は-128~127です。 今回の場合、元の数が-116ですので、左に2ビットシフト(4倍)すると、 -464ですので2ビット足りません。 それで、本来立っていたビット(2桁目と3桁目)があふれてしまった為に 計算が合わなくなりました。 ためしに、10桁(1110001100)で同様の計算をすればうまくいくはずです。
その他の回答 (1)
- seiiiichi
- ベストアンサー率41% (79/190)
確かに、これだけだと、2の補数表現なのか、ただ単に第一ビットが 符号をあらわしているだけなのかよくわかりませんが、とりあえず 後者として話しを進めます。 論理シフトは符号ビットもシフトしますが、 算術シフトは符号ビットはシフトしませんし、シフトされません。 したがって、 【10001100を2ビット右シフト】 → 10000011 (-3) となり、計算は合います。 なので、質問者様の間違いは「符号ビットもシフトしてしまったこと」です。
補足
さっそくのご回答、本当にありがとうございます。 ご回答いただいた方法ですと、スッキリします。 ありがとうございました! 今は単純にそのように理解していこうと思います。 ちなみになんですが、テキスト上では 「シフト演算」の「算術シフト」の「右シフト」は 空いたビットには「符号ビットと同じものを入れる。」 と書かれております。 今回の例では間違いのもととなったところですが、 10001100を算術シフトすると 2桁右シフトすると11100011となり(空いた所に符号ビットを入れる) 2桁左シフトすると10110000となる(空いた所に0を入れる) とテキスト上はなっております。 左シフトと右シフトで、元の数値も結果の数値もどちらも 2の補数表現としてとらえて自分で検算的に 計算すると、今度は右シフトは答えが合うのですが、 左シフトで答えが合いません。 ご回答者様の方法でせっかく答えが合うのに、 「右シフトのときは符号ビットで埋める」という概念自体が 存在する意味がないような気がするのですが。 もしかして、 負の数の左シフトのときは「2の補数」の概念を使わず 先頭ビットは符号ビットとして考えて、後のビットをまんま計算する。 負の数の右シフトのときは全ビットを数値と考えて負の数と捉え 「2の補数」の概念で計算する。 という考え方もできるのでしょうか? なにか考え方で欠けていそうなところなど もしお分かりでしたら教えてください。 たしかにテキストには「2の補数」表現なのか 符号を表しているだけなのかは書かれておらず、 左シフトと右シフトも続けて書かれていますが どちらがどちらの表現なのかなどは書かれていないので 何とも言えません^^ テキスト的には、大まかな概念を説明しただけで それ以上は突っ込むなというところなのかもしれませんが もやもやが晴れたらうれしいです。 よろしくお願いします。
お礼
seiiiichiさん、ありがとうございました! 大変参考になり、理由がわかりました。 そして、左シフトも桁を足して補数での計算してみて、 答えも合いました! いやあ、うれしいです。 「あふれ」、学んだはずなんですが。 慣れるために何度も復習したいと思います。 ありがとうございました。 頑張ります。