シフト演算について

このQ&Aのポイント
  • 基本情報技術者試験の資格試験のための勉強をしているものです。シフト演算のうち、「論理シフト」ではなく、「算術シフト」で理解できない点があります。
  • 左シフトは理解できたが、右シフトがよくわからない。例題では数値の右シフトを実行した結果が理解できない。
  • 先頭ビットの符号ビットがマイナスの数値になることを考慮しながら、右シフトを実行すると結果が合わない。間違っている点を指摘してほしい。C言語については学習していない。
回答を見る
  • ベストアンサー

シフト演算について

基本情報技術者試験の資格試験のための勉強をしているものです。 現在、カテゴリー的には基礎理論の離散数学、 シフト演算のうち、「論理シフト」ではなく、 「算術シフト」で理解できない点があります。 左シフトは理解できたつもりなんですが・・・ 右シフトがいまいちよくわかりません。 以下に例題を表記します。 【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言語にまつわるご回答ですともっとわからなくなりそうです。 単純に間違いを指摘していただけると大変助かります。 よろしくお願いします。

  • RARH
  • お礼率92% (13/14)

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

  • ベストアンサー
  • seiiiichi
  • ベストアンサー率41% (79/190)
回答No.2

#1です。 おっしゃる通り、右シフトの時に符号ビットをそのままシフトするのは、 補数を使っているからです。 補数の場合は、ビットが反転している為、マイナスを表すときは、1が0になります。 理屈で言えば、右シフト(2分の1、4分の1、...)するのに桁の大きいところには 0が入るはずですので、符号ビットが1の時(負の時)には1を入れます。 ただ、今回の補足の例で左シフトの計算が合わないのは、桁数が足りないからです。 8桁の2の補数で表すことのできる範囲は-128~127です。 今回の場合、元の数が-116ですので、左に2ビットシフト(4倍)すると、 -464ですので2ビット足りません。 それで、本来立っていたビット(2桁目と3桁目)があふれてしまった為に 計算が合わなくなりました。 ためしに、10桁(1110001100)で同様の計算をすればうまくいくはずです。

RARH
質問者

お礼

seiiiichiさん、ありがとうございました! 大変参考になり、理由がわかりました。 そして、左シフトも桁を足して補数での計算してみて、 答えも合いました! いやあ、うれしいです。 「あふれ」、学んだはずなんですが。 慣れるために何度も復習したいと思います。 ありがとうございました。 頑張ります。

その他の回答 (1)

  • seiiiichi
  • ベストアンサー率41% (79/190)
回答No.1

確かに、これだけだと、2の補数表現なのか、ただ単に第一ビットが 符号をあらわしているだけなのかよくわかりませんが、とりあえず 後者として話しを進めます。 論理シフトは符号ビットもシフトしますが、 算術シフトは符号ビットはシフトしませんし、シフトされません。 したがって、 【10001100を2ビット右シフト】 → 10000011 (-3) となり、計算は合います。 なので、質問者様の間違いは「符号ビットもシフトしてしまったこと」です。

RARH
質問者

補足

さっそくのご回答、本当にありがとうございます。 ご回答いただいた方法ですと、スッキリします。 ありがとうございました! 今は単純にそのように理解していこうと思います。 ちなみになんですが、テキスト上では 「シフト演算」の「算術シフト」の「右シフト」は 空いたビットには「符号ビットと同じものを入れる。」 と書かれております。 今回の例では間違いのもととなったところですが、 10001100を算術シフトすると 2桁右シフトすると11100011となり(空いた所に符号ビットを入れる) 2桁左シフトすると10110000となる(空いた所に0を入れる) とテキスト上はなっております。 左シフトと右シフトで、元の数値も結果の数値もどちらも 2の補数表現としてとらえて自分で検算的に 計算すると、今度は右シフトは答えが合うのですが、 左シフトで答えが合いません。 ご回答者様の方法でせっかく答えが合うのに、 「右シフトのときは符号ビットで埋める」という概念自体が 存在する意味がないような気がするのですが。 もしかして、 負の数の左シフトのときは「2の補数」の概念を使わず 先頭ビットは符号ビットとして考えて、後のビットをまんま計算する。 負の数の右シフトのときは全ビットを数値と考えて負の数と捉え 「2の補数」の概念で計算する。 という考え方もできるのでしょうか? なにか考え方で欠けていそうなところなど もしお分かりでしたら教えてください。 たしかにテキストには「2の補数」表現なのか 符号を表しているだけなのかは書かれておらず、 左シフトと右シフトも続けて書かれていますが どちらがどちらの表現なのかなどは書かれていないので 何とも言えません^^ テキスト的には、大まかな概念を説明しただけで それ以上は突っ込むなというところなのかもしれませんが もやもやが晴れたらうれしいです。 よろしくお願いします。

関連するQ&A

  • 算術シフトしたら、あれ?

    16進数ので各4ビット(4桁)で2進数で算術シフトしますが、符号部はぬいて元の16進数に戻すのですか?でもそうすると元の数より大幅に減ってしまいますよね。例題の 例題・A4A6(16)を2ビット算術シフトする。 A4A6(16)=1010 0010 1010 0110 (2) ・左へ2ビットシフトする。 1000 1010 1001 1000(2)=A98(16) ・右へ2ビットシフトする。 1110 1000 1010 1001(2)=8A9(16) というように、符号部ぬかしたら増えるはずが減ったり、減るはずが増えたりと。なんか変ですよね。 ちなみに符号部すべて入れて考えたら、 左へ算術シフト 8A98(16) 右へ算術シフト E8A9(16) 増えるはずが減って、減るはずが増えるというあべこべになってしまいます。 超基本的ことなんですが、なぜか本に記載されていなかったので書きました。ご協力ください。

  • シフト演算の左シフトが何で72になるのでしょうか?

    ■やりたいこと ・100を左に1ビット(1けた)シフトさせたら2倍になることを確かめたい ■試したこと ・100を2進数へ変換 → 1100100 ・左に1ビット(1けた)シフト → 1001000 ・1001000を10進数へ変換 → 72 ■質問 ・どこで間違えているのでしょうか?

  • [2進数 シフト演算 除算について]

    [2進数 シフト演算 除算について] シフト演算について勉強中です。ご協力お願い出来たら幸いです。 乗算について例えば『1010』(符号ビットを考えず)を2倍 4倍 8倍(2のn乗)した場合 ビットを2倍であれば1つ、4倍であれば2つ・・・左に シフトすれば良いというのは理解しました。 また3倍 5倍などのケースも、 3倍であれば1ケタ左にシフトした数+1010で求まる事も理解しました。 問題は除算です。他の質問を探ってみたのですが、考え方は一緒という回答で・・・詰まっています 除算は右シフトとの事ですが 先ほどの例である『1010』(10)ですがこれを1/2、つまり2で割ると 1つ右にシフトし1010→0101 となり 1010を1/4する場合右に2ビットシフトし 1010→0010.10 となり理解は出来ます。 しかし1/3 、1/5といった場合の計算の仕方が分かりません。 余りを出さないという考えで(近似値になると思いますが) 解き方をご教授願えたらと思います。

  • シフト演算子について・・・意味がわかりません(T_T)

    左シフト演算子<<は最上位ビットの上位を削除して最下位に0を追加、 右シフト演算子>>は最下位ビットが削除されて、最上位ビットに最上位ビットと同じ値が補充される、 論理右シフト>>>は最下位ビット削除され、最上位に0が補充される。 と、ここまではわかりました・・・ ある問題で int n = -1>> 31; でnはいくつになるか?というのがあったんですが、 解説の意味がわかりません。 回答はー1です。 「>>演算子によるシフトでは符号ビットが拡張される」 意味がわかりません・・・(@_@) 「>>>演算子であったなら、符号ビットがゼロになるのでN=1となる」 え・・・???!!! ふごーびっと??? シフト演算子ですから、 「-1の31こ右にビットをシフトする」 んだな・・・と思ったところ、 まったくどう考えてよいのかわからず、 回答を見たところ、余計わからなくなりました。 だれかたすけてください(T_T)

    • ベストアンサー
    • Java
  • 算術シフト演算が成り立つ理由がイマイチ・・・

    算術シフト演算で右シフトにしても左シフトにしてもシフトで空いたビットに符号ビットと同じ物を入れたり0を入れたり、溢れたビットを破棄したり・・・ というのがどうして成り立つのかがイマイチわかりません。 手元の本を見てもWebで探してもそういうことは細かく書かれていなくてよくわからないのです。 レポートで書かなければいけないのにこのままでは答えが出るのが間に合いそうもなく助けを借りたいと思い質問させて頂きました。 どなたかわかる人が居ましたらよろしくお願いします。

  • ビットシフトについて

    12ビットのデータ(符号付き)を16ビットのデータに変換したいです。 自分なりに考えたのですが・・・ 最上位ビット(符号を表すビット)の位置が違うので左に4ビットシフト、 右に4ビットシフトします(どちらも算術シフトとします) 例  0000 1011 1101 0101 (12bit のデータ) →1011 1101 0101 0000 (左にシフト) →1111 1011 1101 0101 (右にシフト) こうするとたしかに16ビットのデータの最上位ビットには12ビットのデータの符号が 反映されるように思えるんですが、符号を除いた値そのものが変わってしまいますよね? どうしたらいいでしょうか 切羽詰まってて文章めちゃくちゃで分かりづらいかとは思いますが、解答よろしくお願いします。

  • シフト演算の問題です

     2進数の値を左へn桁移動すると、もとの値の2^n倍になる。 例えば、左へ2ビット桁移動するともとの値の4倍となる。  この性質を利用して、左へ桁移動した値を複数加えることで行う乗算を考える。 なお、ここでは、桁移動して空いたビットには0が入るものとし、負数は考えないものとする。 左へ桁移動する関数として、"SHIFT(値、桁数)"を使う。 この関数は、引数の"値"を"桁数"ビット左へ桁移動した結果を返す。  もとの値をaとし、これを10倍するには、2倍した値と8倍した値を加えればよいので、次のような式になる。  SHIFT(a,1)+SHIFT(a,3) また別の考え方で10倍しようとすると、次のような式になる。  SHIFT((SHIFT(a,x)+a),y) 答えはx=2 y=1 です。 解説をお願いします。

  • 「左算術シフト」について

    「算術シフト」についての質問です。 算術シフトには「右シフト」「左シフト」というものがあり、 「右算術シフト」の場合は、右シフトする時、一番左側の数(符号)が 「0」の場合→一番左側から「0」を補う。 「1」の場合→一番左側から「1」を補う。 ということですが、「左算術シフト」だとこんな感じでよろしいのでしょうか? 一番左側の数(符号)→そのまま(固定のまま) 二番目の左側の数(符号)→捨てる 三番目以降の左側の数(符号)→左へスライド 最後(一番右側)の数(符号)→右からゼロを補う ↑私の考えだと「左算術シフト」はこういうのものだと思いますが、こんな解釈でよろしいのでしょうか? よろしくお願いします。

  • シフト演算子

    わたしの使用している参考書で 8ビットのデータを左に2ビットシフトすると、 1111 1111 ↓ 1111 1100 となるとあります。この場合、シフトした値が元の値の4倍になると勉強したのですが、実際には元の値より減っているように思えるのですが・・。教えてください。よろしくお願いします。

  • 論理シフトについて

    コンピュータの論理シフトについて質問があります。 シフトしてオーバーフローした場合は、コンピュータ内部においては演算結果が反映されているのでしょうか? 例えば、8ビット表記で (10100001)_2 =(161)_10 で左に一桁シフトしたとすると (01000010)_2 =(66)_10 という表記になると思うのですが、このようなシフトをすると値が小さくなってしまう という考え方をすればいいのでしょうか? 回答よろしくおねがいします。

専門家に質問してみよう