符号付き整数

14.2.1. 符号付き整数

まずは、最も基本的な数である整数をコンピュータ内で表現する方法について説明します。

符号無し整数の符号化 #

非負整数の符号化は、 2 進法をそのまま用います。 これを、次の符号付き整数の対比で 符号無し整数 と呼びます。 何バイト使うかで、表現できる範囲が決まります。 \(m\) ビットを用いると \(0\) から \(2^{m-1}\) の範囲の整数が表現可能です。たとえば 1バイト = 8 ビットなら、 \(0\) から \(255 = 2^8-1\) までの整数が表現できます。

bits min max
8 0 255
16 0 65535
32 0 4294967295
64 0 18446744073709551615

計算機で使う標準的なデータ長が、標準的な整数の表現になります。 これは CPU (中央演算装置) が 1 回の命令で効率的に扱える大きさから決まります。 現在のほとんどのPCでは 64bitです。 2000年頃は32bitが主流でした。現在でも組み込み機器などでは32bit以下も使われています。 これをワード (word) とも呼びます。

四則演算 #

数の四則演算は2進でも10進でも同じです。 加算の例を示します。

\[6_{(10)}+5_{(10)}=11_{(10)}\] \[0110_{(2)}+0011_{(2)}=1001_{(2)}\]

オーバーフロー #

演算結果が表現範囲を超えることを オーバーフロー (overflow) と呼びます。 \( m\) ビットで表せる非負整数は \( 0\) から \( 2^{m-1}\) までです。 この範囲内の数同士であっても、演算結果が範囲を外れてしまうことがあります。たとえば \(m=4 \) ビットの加算で、以下のように結果の表現に 5bit 必要になった場合、5bit目 (左端の1) は無視されます。 \[1101_{(2)}+0101_{(2)}=10010_{(2)} \underbrace{= 0010_{(2)}=2_{(10)}}_{\text{overflow}}\]

オーバーフローが発生したときに、上記のように誤った結果で淡々と計算が進むか、例外処理が発生するかは環境や設定によります。

符号付き整数の符号化 #

正負どちらもとる整数を符号付き整数と呼びます。 負の整数も含めて符号化するにはどうすれば良いでしょうか? 通常は 補数表現と呼ばれる方法を用いて負の整数を表します。 日常生活では-1のように- (マイナス記号) を用いますが、2進符号化では0,1しか使えません。

\(m-1\) ビットの 正の2進数に対する補数を「足すと \(2^m\) になる数」と定義します。 \(m=4\) の例を表の左2列に示します。どの行も、数と補数の和が 1000 であることを確認してください。数と補数は1:1に対応します。

補数 10進数 解釈 (10進)
001 111 1 -1
010 110 2 -2
011 101 3 -3
\(\vdots\) \(\vdots\) \(\vdots\) \(\vdots\)
111 001 7 -7

これを利用して \(m\) ビットの符号付き整数を、 \(m-1\) ビットの非負整数と、補数を利用した負の数で表します

最上位bitが0
非負の 2進数。
最上位bitが1
負の数 — 残りの \(m-1\) bitを非負整数と解釈し、それに \(-2^{m-1}\) を加えたもの。上記の表の「補数」のbit列に対する一番右の列と同じ。

\(m\) bitでの表現範囲は \([-2^{m-1}, 2^{m-1}-1]\) です。 負の数の範囲が1多い理由は -0 は表現せずにその分を負の方に割り当てたためです。

bits min max
8 -128 127
16 -32768 32767
32 -2147483648 2147483647
64 -9223372036854775808 9223372036854775807
範囲は十分?
32bitの表現範囲は約20億で、日常生活には十分でも、たとえば国家予算を扱うには不足します。 64bit あれば、人が数えるものには十分でしょうが、原子とか宇宙を扱うには桁が不足します。 巨大な桁を扱う場合は、次の浮動小数点数を使うことが一般的です。

補数表現の利点 #

補数表現の利点は、負の数を1大きくしたときに、対応する補数表現を整数としてみれば1大きくなっていることです。 これにより、符号付き整数も符号無し整数と同様に四則演算をできます。

たとえば \(-1+1=0\) という計算を 4 ビット符号付き整数で行うと、以下のように 符号無し整数として計算して overflow が発生した結果とまったく同じです。

\[\underbrace{1111_{(2)}}_{-1_{(10)}} +\underbrace{0001_{(2)}}_{1_{(10)}} = \underbrace{10000_{(2)} = 0000_{(2)}}_{\text{(overflow)}}\]

この点はコンピュータの中で整数の計算を担うハードウェアの設計で有利になります。

他の表現
符号付き整数を表すには、他の方法もあります。簡単には、「[0,2048]の非負整数から 1024 を引く」などと約束すれば、0は-1024に、1024は0になります。
数値の符号化 符号付き整数 浮動小数点数