アプリ版:「スタンプのみでお礼する」機能のリリースについて

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

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

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

【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言語にまつわるご回答ですともっとわからなくなりそうです。

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

A 回答 (2件)

#1です。



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

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

ためしに、10桁(1110001100)で同様の計算をすればうまくいくはずです。
    • good
    • 0
この回答へのお礼

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

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

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

お礼日時:2009/12/30 14:09

確かに、これだけだと、2の補数表現なのか、ただ単に第一ビットが


符号をあらわしているだけなのかよくわかりませんが、とりあえず
後者として話しを進めます。

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

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

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

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

この回答への補足

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

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

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

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

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

もしかして、

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

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

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

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

補足日時:2009/12/30 11:46
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!