わらばんし仄聞記

南の国で引きこもってるWeb屋さん

補数表現について

補数って?

2進数を扱うとき、符号付きの場合を考えると決まって出てくる「2の補数表現」ってやつ。 これ自体は「補数」と一般的に言われるものの定義から明確なので、何も問題は無いんです。

補数 - Wikipedia

wikipedia先生でも述べられている通り、補数とは\( {b} \)進法において、自然数\( {a} \)を表現するのに必要な最小限の桁数を\( {n} \)としたとき

\begin{align*} {b}^{n} - {a} \end{align*}

である。つまり「補数」とは、表したい数について「必要な桁数 +1」桁の最小の数から、その表したい数を引いた値。言い換えれば、表したい数に対して和をとれば桁が上がる値のなかで最小のものということになる。
この辺りについては 原書で学ぶ64bitアセンブラ入門(2) - わらばんし仄聞記 でも触れましたが、例えば10進数で考え、61という値の補数は39になります。

以上より、2進数においては各ビットを反転させたものに1を足したものが「2の補数」であることは容易に理解出来ます。

1の補数表現

さて、悩みのタネであった「1の補数表現」です。
先述の定義にそのまま当てはめて考えてしまうと、「1進法」?なんだそれは・・・。と、完全にポルナレフ状態になってしまいます。

さて、またもwikipedia先生の出番です。
符号付数値表現 - Wikipedia

こちらで書いてある通り、英語の時点では「1の補数」とは "ones' complement" であり、「2の補数」は "two's complement" と表されています。2の補数についてはいいでしょう。英語の方でも2を基数として補完する値ということが読み取れます。
問題の「1の補数」ですが、 "ones'" となっています。-sで終わる複数形の名詞について所有格を示す為には、末尾にアポストロフィだけを付記する事からわかる通り、これは、複数の "1" の並びを補う値という意味が読み取れます。

これはつまり、最初にリンクを貼ったwikipediaのページにある「減基数の補数」を2進数の場合において表している訳で、実際その辺りの書き分けが英語では出来ますよということも述べられていますね。
減基数の補数は英語で "diminished radix complement" というそうで、そこら辺については以下を参照してもらうといいかと。

Method of complements - Wikipedia, the free encyclopedia

つまり

補数をとる対象Nについて、適当な値aについて考えると

N's complement -> Nの冪乗と相補関係(aに対して、「a以上であり、かつ最小のNの冪乗」となるために足すべき数)
Ns' complement -> Nを複数並べたものと相補関係(aに対して、全て桁がNで埋まるように足すべき数)

という違いが存在する。

一般的に「2の補数」と合わせて述べられる「1の補数」は「2進法における減基数の補数」の事であり、これはつまりがビットを反転させたものと一致する。昔は負数の表現に、先頭のビットを1として、残りのビットを対応する正の数を反転させたものを使っていたそうです。その辺りはwikipediaの方が詳しいのでそちらを見てもらったほうがいいですが、この場合、0と-0という0の表現が2つ出来てしまう事になる為に計算が複雑になるため、現在、負の値については+1して-0の位置に-1が来るようにしたものを使います。

さて、2の補数が各ビットを反転させたものに1を足したものとして表現できることは先に述べたとおり。また、直前で述べた負数の表現は「1の補数を求めた(=ビットを反転させた)ものに1を足す」事によって-0を省いた負数表現をしていました。つまり、やっている事は同じ操作ですね。
これより、「負の値を求める時は2の補数」を求める。また、その導出については「全部のビットを反転させて1を足す」という操作の全てがリンクしたことになります。

ほとんどwikipedia読んで思ったことを書いたばかりな感じですが、自分の中では全部つながってスッキリした感じがします。
なにか間違っている点があったら、ご指摘お待ちしてます。