- ベストアンサー
2進数ビット列の算術シフトについて
- 2進数ビット列の算術シフトとは、ビット列を指定されたビット数だけ左または右にシフトする操作のことです。
- プラスの数値を算術右シフトすると、あふれたビットを破棄して範囲で表現できない部分を切り捨てます。
- マイナスの整数の場合、単純に「-0.5」の部分を切り捨てるだけではなく、切り捨てた結果が負の整数として正しく表現されるように調整されます。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
No.1です。 >どうしても分からないのは、(中略)つまり絶対値で0.5の差が出る理由です。 くどくなりますが、すべては『2の補数を使用するから』というところに集約します。 以下は4bitで説明します。 4bitの場合、表せる範囲は「0000」~「1111」の16種類です。 正負の数を「1の補数」で表現した場合 0000:0 1111:0(本来は使用しないが扱い上は0) 0001:+1 1110:-1 0010:+2 1101:-2 0011:+3 1100:-3 0100:+4 1011:-4 0101:+5 1010:-5 0110:+6 1001:-6 0111:+7 1000:-7 となります。「-7~0~+7」までの「15」の数値を表します。 対して「2の補数」は 0000:0 1111:-1 0001:+1 1110:-2 0010:+2 1101:-3 0011:+3 1100:-4 0100:+4 1011:-5 0101:+5 1010:-6 0110:+6 1001:-7 0111:+7 1000:-8 となります。「-8~0~7」までの「16」の数値を表します。 つまり、+(0も含む)と-で表現できる範囲が1つずれているのです。 あえて誤解するように書けば、「0」が中心ではなく「-0.5」がデータ的な中心です。 絶対値は、データの中心である「-0.5からの相対位置」になりますから「+1」の絶対値なら「1.5」、「-1」の絶対値は「0.5」、絶対値の差は「1」となります。 この値を「プラスとマイナスだから/2」とすると「0.5」になります。 それによって発生する問題です。 正直なところ、なんとか理屈づけて納得しようとしても難しいので「こういうものだ」と割り切ったほうがいいと思います。
その他の回答 (4)
- SilverThaw
- ベストアンサー率32% (260/806)
No.1です。 >(1)n進数の補数にnの補数とn-1の補数の二つがある理由が分かりません。 正直、私も知りたいです。 このおかげで私も過去に「2の補数」のつもりで作っていたら、実は「1の補数」でイタイ目を見たことがありますので(単に、仕様の確認漏れだけなのですが) 個人的な考えですが、 ・単純にわかりやすくビットを反転しただけ(+1の処理がいらない、回路も小さくなる) ・「0000 0000」を起点として「0000 0001」「0000 0010」……と、「1111 1111」「1111 1110」……と進んでいくのがわかりやすいから ではないかと考えたりしてますが。 >(2)一番分からないのは、このシステムで100を2進数で8ビットで表したものを(後略) 結論から書くと「10進数」ではなく「2進数(2の補数表現)」で処理しているためです。 単純に10進数で算出した際の小数点を切り捨てているわけではありません。 「2進数(2の補数)」で考えるとすっきりします。 今までと同じく8bit表現で記載します。 「+100」は「0110 0100」、「-100」は「2の補数」では「1001 1100」で表されます(算出方法はNo.3参照)。 これを「右に3ビット算術シフトする」と 「0110 0.100」(+100)は「0000 1100」=「12」 「1001 1.100」(-100)は「1111 0011」 となります(上記はわかりやすくするために、シフトした際に一番下位のbitの位置に「.」をつけています)。 この「1111 0011」は「1111 1111」(-1)から数えて13番目であり「-13」となります。 (尚、マイナス値からの絶対値を求める場合も、「bitを反転して+1」は同じです。)
補足
ご丁寧に毎回詳しいご回答を本当に有難うございます。ただ悲しいですけど、自分には向かないのか・・・どうしても分からないのは、(1)+100を2進数で8ビットで表したものを右に3ビット算術シフトする場合は+12になり(2)-100を同じように処理した場合、-13になる、つまり絶対値で0.5の差が出る理由です。甘えすぎかも知れませんが、もし、可能でしたら、是非ご教授下さい。
- SilverThaw
- ベストアンサー率32% (260/806)
No.1です。 >(前略)(残ったビットを10進数表示した場合の絶対値が、正負でことなる理由が分からないのです)もしよろしければご教授願います。 結論から書くと「マイナス値を表す手法が『2の補数』基準」で考えているからです。 まず、「2進数」は理解されていますか? また、「マイナスを表すための方法」については? ここが理解できていないと難しいです。 以下は8bitの2進数で説明します。 10進数の「+3」は2進数では「0000 0011」と表します。 これを右に1bitシフトすれば「0000 0001」となります。 一番下位ののbitが追い出されるため、結果は「1」となります。 対して「-3」は「2の補数」で表すと「1111 1101」となります。 「2の補数」はマイナス値を表す方法の一つで、正の値のbitの0/1を逆転した値「+1」することで値を表します。 これにより、マイナス値の場合は必ず最上値のbitが「1」になります。 「-3」の場合は「0000 0011」をbit反転して「1111 1100」、それに「+1」して「1111 1101」となります。 この値を右に右に1bitシフトすれば、桁あふれし「1111 1110」となります。 「2の補数では」この値は「-2」です。 ちなみに、マイナス値の手法には「1の補数」というものも存在します。 この場合「-3」の値は「1111 1100」。 右に1bitシフトした値は「1111 1110」となり、結果は「-1」となります。
補足
ご丁寧に詳しい補足説明有難うございます。確かにまだ理解が曖昧な部分あると思います。もし更に教えていただけるなら(1)n進数の補数にnの補数とn-1の補数の二つがある理由が分かりません。(2)一番分からないのは、このシステムで100を2進数で8ビットで表したものを右に3ビット算術シフトする場合と-100をこの補数表現で同様の行為(右に3ビット算術シフトする)を行った場合とで+と-の符号を除いた絶対値に違いが出ることです。前者は10進数表記では12.5から小数点以下の0.5(2進小数点以下の1ビット)を切り捨て、12?後者もやはりこの算術シフトによる右の桁の切り捨てで小数点以下のビットは消えるはずなのに-13?(絶対値13)?+と-では0と1は反転するのは分かるのですが、この計算結果になるロジックが分からないのです?
- Tacosan
- ベストアンサー率23% (3656/15482)
「負の数の丸め」は表現として微妙なところがあります. たとえば「-1.5 を整数に丸める」ときに「-2 とする」のか「-1 とする」のかという選択があります. 実際には正の場合にも選択肢が考えられます. ということで, 丸めの方法には ・負の無限大への丸め (小さい方に丸める) ・正の無限大への丸め (大きい方に丸める) ・0 への丸め (絶対値の小さい方に丸める) ・最近値への丸め (最も近い値に丸める: 中間のときは偶数にするのがきっと正しい) などがあります. 今の場合は「負の無限大への丸め」となるので -1.5 が -2 になります. 解釈によっては「-1.5 を -2 にするのは -0.5 の部分を切り捨てたんだ」とも見なせますけどね.
補足
すみません。丸めというよりは単純に算術右シフトした場合に、小数点以下にあたるのビットを切り捨てねばならない場合のことです。
- SilverThaw
- ベストアンサー率32% (260/806)
「(-3)÷2」とした場合、8bitでの-3の「2の補数」は2進数で表すと「1111 1101」。 「2で割る」ことにより、右に1bitシフトした値は「1111 1110」。 これは「-2」にあたるから。
補足
早速のご回答有難うございます。ただ小数点以下を表示しないビット列で右算術シフトした場合でビットが一つ溢れた場合、プラス部なら0.5にあたるビットの切り捨てとかで理解出来るのですけれども、負数で はなぜ単純に-0.5に当たるビットの切り捨てとならないのでしょうか?(残ったビットを10進数表示した場合の絶対値が、正負でことなる理由が分からないのです)もしよろしければご教授願います。
お礼
ほんとうにご丁寧に分かりやすい解説有難うございました。SilverThaw 様の親切さにただ感涙するのみです。感謝いたします。