コンピュータの数値表現

誤差についての誤解

コンピュータでの数値計算には誤差がないという誤解がある。例えば、 や  を計算すると、正確に 1 が得られると期待するかもしれない。しかし実際には、、 はコンピュータや十進電卓（2×5＝10）では 0.9999999999999999、 はコンピュータや六進電卓（2×3＝10）では 0.5555555555555555 のような結果となったり、場合によっては 0.99999999923475 や 0.55555555512243 のような値になることもある。後者の値 (十進数0.99999999923475 や六進数0.55555555512243) はバグではなく、二進法の浮動小数点数による近似の結果生じる。ある種の任意精度演算系や、数式処理システムでそういった演算に対応している場合は、1 や 0.9999999999999999… や 0.5555555555555555… という結果が得られるものもある。
また、電卓などでは、内部計算において、十進数なら9、六進数なら5が幾つかか連続する場合は繰り上がりをするといった処理により、表示画面においては誤差がないように見えることもある。なお、十進法や六進法など因数に奇数が含まれるN進法の浮動小数点数では誤差が発生しないという誤解もあるが、十進法の浮動小数点数でも本来なら 0.9999999999999999 のような数になる。実数型という用語は、実数を正確に表せる型という誤解を生む可能性がある。

ビット・バイト・ニブル

コンピュータにおける二進法による非負整数値の表現を説明する。

バイト

バイト（byte）は8ビットで、256種類の値を表せる。バイトを単位とするコンピュータの多くは、ワードとして8に2の冪をかけたビット数（例えば、16ビット、32ビット、64ビット）の単位をよく使うことが多い。
なお、バイトは必ずしも8ビットではなく、5ビット〜9ビット程度をバイトとするコンピュータもあったことなどから、「オクテット」という語もある。オクテットは必ず8ビットであり、任意のコンピュータを接続する可能性を考慮しているコンピュータネットワークの分野では「オクテット」を好んで使うことも多いが、近年はバイトの語も、ほぼ8ビットを指すようになっている。

その他

目的によっては、以上のような方法とは異なる表現法が便利なこともある。例えば、グレイコードなどがある。

符号付数値表現

符号付きの数値の表現法はいくつか存在する。必ずしも「符号ビット」があるとは限らない。例えば、ゲタ履き表現では、ゲタの値によっては「符号ビット」としては扱えない。符号ビットがある場合は、最上位ビットが符号ビットのことが多い。なお、符号ビットについて「1なら負の数を表し、0なら正の数を表す」といったように考えるのが自然なのは「符号と絶対値」表現の場合だけであり、たとえば「2の補数」表現であれば、最上位ビットは −(2ᴺ) の重みを持つ桁である、と解するのが自然である。

符号と絶対値

「符号と絶対値」表現は、1ビットの符号ビットと、絶対値を表す残りのビット群からなる。例えば、4ビットの場合で、MSBの、0が正、1が負を示すものとすると、
0101 = +5
1101 = -5
となる。浮動小数点数はたいていがこのような形をしている。ただし、絶対値の部分が指数部と仮数部に分かれている。

1の補数

1の補数とは、数のビット毎の反転が符号を反転させるとする表現である。これはビット単位のNOT演算に他ならない。例えば、
0101 = +5
1010 = -5
1の補数でも符号-仮数部表現でも、ゼロの表現が二種類存在するという問題がある。このため、どちらも最近のコンピュータでは滅多に使われない。1の補数では、
0000 = +0
1111 = -0
符号-仮数では、
0000 = +0
1000 = -0

2の補数

最近のコンピュータでは2の補数表現が広く使われている。2の補数は、ビット毎のNOT演算を施した後に1を加算することで得られる。例えば、
0101  =  +5
1011  =  -5
したがって、
  0000  =  十進 0    1000  =  十進 -8
  0001  =  十進 1    1001  =  十進 -7
  0010  =  十進 2    1010  =  十進 -6
  0011  =  十進 3    1011  =  十進 -5
  0100  =  十進 4    1100  =  十進 -4
  0101  =  十進 5    1101  =  十進 -3
  0110  =  十進 6    1110  =  十進 -2
  0111  =  十進 7    1111  =  十進 -1
この方式では整数であれば、16ビットで −32,768 から 32,767 の範囲、32ビットでは −2,147,483,648 から 2,147,483,647 の範囲を表現する。
2の補数の利点は、加減算かつオーバーフローを考えない範囲に結果が収まるような限りであれば、符号を気にせず符号無しの整数と同様に扱える点である。
例えば、5 + (-5) は以下のようになる。
  0101
 +1011
 10000
ここで、数値は4ビットで表しているので、演算結果も4ビットでなければならず、したがって先頭の1は捨てられ、結果として期待した通りの0が得られる。
演算において符号を気にする必要がないのは、2ⁿ を法とした合同式になっているためである。例えば、15 ≡ -1 (mod 16) である。コンピュータは一般に固定のビット数で数値を表すので、法が一定であり理想的である。2の補数表現と符号なし表現の違いは、大小比較方法と表示方法である。
2の補数表現の唯一の奇妙な点として、表現可能な最も小さい数（16ビットなら -32768）の2の補数をとると自分自身になる点が上げられる。しかし、それが問題となることは滅多に無い。むしろ、符号無しの場合にオーバーフローになる演算が、2の補数表現ではごくあたりまえの、0をまたいだ計算（正確には、負の整数と非負整数にまたがった計算）であることのほうが、慣れるまでは非直感的かもしれない。

固定小数点数

固定小数点数形式は、金銭勘定など浮動小数方式と相性が悪い場合、すなわちビジネスにおける計算（表計算ソフトやCOBOLなど）でよく使われる。「浮動小数点数の精度では充分ではない場合に採用される」というのは誤解である。単精度の場合に足りないようであれば、それは同じ長さの固定小数方式であっても足りてない。
整数部と小数部のビット数は、必要とされる精度や範囲に十分なように選ばれる。例えば、32ビット形式では、整数部に16ビット、小数部に16ビットといったように設定される。
桁位置の重み付けは、整数部と小数部で連続的となる。例えば整数部が、8の位、4の位、2の位、1の位となっている場合、小数部は1/2（0.3₍₆₎、0.5₍₁₀₎）の位、1/4（0.13₍₆₎、0.25₍₁₀₎）の位、1/8（0.043₍₆₎、0.125₍₁₀₎）の位と続く。
例:
                     　　　    　 整数ビット群 　  小数ビット群   0.5₍₁₀₎   = 0.3₍₆₎    =   ½  =  00000000 00000000.10000000 00000000
   1.25₍₁₀₎  = 1.13₍₆₎   =  1¼  =  00000000 00000001.01000000 00000000
   7.375₍₁₀₎ = 11.213₍₆₎ =  7⅜  =  00000000 00000111.01100000 00000000
ただし、この形式では二進数では表せない数が出てくる。例えば、1/3（三進数0.1 = 六進数0.2）や1/5（十進数0.2）は正確に表すことはできず、最も近い値は以下のようになる。
  13107 / 65536  =  00000000 00000000.00110011 00110011  =  0.1999969... 十進数の場合  13108 / 65536  =  00000000 00000000.00110011 00110100  =  0.2000122... 十進数の場合
これは、桁を増やしても正確に表すことはできない。2の冪数で位取りが作られているためである。従って、「1/3」や「1/5」といった奇数分割ができない。六進数0.2（すなわち1/3）は二進数では 0.0101…、六進数0.04（すなわち1/9）は二進数では 0.000111000111…、十進数0.2（すなわち1/5）は二進数で 0.00110011… というように無限小数になる。

プログラミング言語

低水準言語では、符号の有無や固定小数点か浮動小数点かを気にする必要がある。例えば浮動小数点の加算なのか整数の加算なのかによって、使用する命令が全く違ったものとなる。
LISPやPythonといった高水準言語では数値のデータ型はより抽象的であり、rational、bignum、complex などがある。それらの言語では、低水準言語と比べ、より抽象化され扱いやすいものとしてそれらの値が提供される。しかし「どんな数値であっても算術演算を正しく処理することが期待できる」というのは間違いで、コンピュータでは真の実数を扱うことはできないのだから、これらのデータ型でも同様に、それぞれの性質に注意して扱わねばならないことに違いは無い。演算子オーバーロードなどによって、符号無し整数、符号付整数、浮動小数点数、複素数など、複数のデータ型に対して、同じ見た目の式になるような言語もある。