Yamamoto's Laboratory
電子計算機
  第7回
講義ノート 2003年度 電子計算機 (論理回路) コンピューター内部の負の数の表現

電子計算機コンピューター内部の負の数の表現

コンピューター内部の負の数の表現方法を示します.コンピューターでは全てビットで数を示します.したがって,マイナス記号「−」を使うことができません.そこで,現代のコンピューター内部では「2の補数」という表現方法が用いられます.本講義では,負の表現方法を学びます.

目次


講義を始める前に

本日の授業のテーマ

本日の授業のテーマは,以下のとおりです.

  • ビットと2進数
  • 小数
    • 数の正負の表現

本日の授業のゴールは、以下のとおり。

  • コンピューター内部での負の数の表現方法がわかる。

先週の復習

  • 基数の変換(8, 16 → 10進数) \begin{align} (376)_8 &= (3\times 10^{2}+7\times 10^{1}+6\times 10^{0})_8 \nonumber\\ &= (3\times 8^{2}+7\times 8^{1}+6\times 8^{0})_{10}\label{eq:376_8}\\ &=(3\times 64+7\times 8+6\times 1)_{10}\nonumber\\ &=(254)_{10} \nonumber\\ \end{align} \begin{align} (376)_{16} &= (3\times 10^{2}+7\times 10^{1}+6\times 10^{0})_{16} \nonumber\\ &= (3\times 16^{2}+7\times 16^{1}+6\times 16^{0})_{10}\label{eq:376_16}\\ &=(3\times 256+7\times 16+6\times 1)_{10}\nonumber\\ &=(886)_{10} \nonumber\\ \end{align}
  • 整数の基数の変換(2→8, 16進数)。8進数への変換は第0ビット(最小桁)から3桁ずつ区切り、16進数への変換は4桁ずつ区切り計算します。

    図1: 各進数とビットの関係。(3434)10を2, 8, 16進数で表している。(3434)10=(6552)8=(D6A)16

  • 小数の基数の変換(2→8, 16進数)。8進数への変換は小数点の次の桁から3桁ずつ区切り、16進数への変換は4桁ずつ区切り計算します。

    図2: 2進数小数を8および16進数の小数に変換。(0.100110101111)2 = (0.4657)8 = (0.9AF)16

  • 桁数が合わない場合は、先頭に必要なだけ、ゼロを書き足して考えます。例えば、16進数へ変換する場合、(101100)2=(00101100)2 や (0.111111)2=(0.11111100)2として計算します。
  • 小数、整数の基数の変換(8, 16 → 2進数)。16進数から2進数への変換は、16進数の各桁を(1, 2, 4, 8)の和に分けて、それぞれのビットに対応させます。8進数の場合は、(1, 2, 4)の和に分けます。

    図3: 16進数から2進数への変換。(B7)16=(10110111)2

  • 基数の変換(10 → 進数8, 16)。2つの方法が有ります。
    1. 一旦、2進数へ変換した後、8及び16進数へ変換する。
    2. 整数の場合、8又は16で割って、その余りが各桁になる。小数の場合は、8又は16を乗じて、整数部が各桁になる。

負の数の表現

整数や小数の正の数の表現は非常に簡単でした。しかし、負の数の場合、事情が異なります。負の数の小数となると更にややこしいので、ここでは負の整数のみを取り扱うことにします。通常は、数の前に「–」の符号をつけて、負の数を表します。コンピューター内部には、マイナスの符号などありませんから、それに対応した何かが必要です。負の数を表す約束事を作る必要があります。いろいろな負の数を表す約束事(表現方法)が考えられます。数多くの負の表現方法がある中で、われわれが使うのは、

  • 便利であること
  • 表現が簡単であること
  • ハードウェアーの実現が簡単であること

などを基準にして、実際に使うものを選択します。通常は、最期に紹介する2の補数表現を使いますが、ほかの表現方法も紹介しておきます。コンピューターの情報の単位は8ビットの場合が多いです。そのため、これ以降は8ビットで話を進めます。

絶対値表示

絶対値表示とは、符号のためにビットを1つ設けて、あとは絶対値で表現する方法です。たとえば、図4のような表現です。人間にとって、この表現は分かりやすいですが、機械にとって良いか否かは別です。

図4: 計算機内部の負の整数の表現(絶対値表示)

1の補数表示

1の補数表示とは、絶対値のビットを反転する方法です。したがって、第7ビットが符号を表すことになります。この方法の欠点は、00000000 と 11111111 がともにゼロを表すことになります。

図5: 計算機内部の負の整数の表現 (1の補数表示)

2の補数表示

2の補数の表現が、現在、計算機内部で普通に使われている方法です。これは、非常に重要です。図6に示しますが、手順は、

  1. 表したい負の数の絶対値を2進数で表現し、ビットを反転する。
  2. それに、+1 加算する。

です。絶対に覚えてください。

要するに、先に示した1の補数表示に1を加えた表示方法です。

図6: 計算機内部の負の整数の表現 (2の補数表示)

この表現方法のイメージを図7に示します。ここで重要なことは、第8ビットを無視すると、2進数が連続していることです。

図7: 距離計イメージ(2の補数表示)

この方法のメリットは、負の数の加算が加算器でできることです。これが可能だと、減算はその2の補数を計算して、加算器で出来ます。負の数の加算と正の数の減算は同じなので、負の数の加算が加算器で出来ることが重要です。

それでは、なぜ、2の補数表現だと、負の数の加算が加算器で可能なのでしょうか?。理論的に説明をしましょう。ある正の整数をxとしましょう。その負の数、-x は 2 の補数表現では、

\begin{align} [-x]=(FF-x+1)_{16}\label{eq:comp2_y-x} \end{align}

となります。左辺の [-x] が -x の意味です。[ ] の意味は、括弧内の負の整数を計算機内部の表現を意味しています。これは、私が作った表記ですので、一般には用いられていません。右辺の FF-x がビット反転です。それに 1 を加えて、2の補数の表現としています。

つぎに、ある整数 y を考えて、y-x を計算してみましょう。

\begin{align} [y-x]=(y+FF-x+1)_{16} \end{align}

FF-x+1 はあらかじめ計算されて、コンピューター内部のメモリーに格納されているので、[y-x]は加算器で可能です。

これはあたりまえです。重要なことは、この結果が負の場合、2の補数表現になっており、正の場合、そのままの値になっていることです。最初は、y-x が負になる場合を考えましょう。すると式\eqref{eq:comp2_y-x}は、

\begin{align} [y-x]=(FF-(x-y)+1)_{16} \end{align}

と変形できます。この場合、絶対値が (x-y) なので、(1) 絶対値のビット反転,(2)+1加算となっています。つぎに、y-xが正になる場合を考えましょう。すると式\eqref{eq:comp2_y-x}は、

\begin{align} [y-x]&=(y-x+FF+1)_{16} \nonumber\\ &=(y-x+100)_{16} \end{align}

となります。100は計算機内部では、桁上がりを示します。8ビットの表示では無視されます。したがって、内部の表現は、正しく表せます。

どの方法が有利か

絶対値表示で負の数を減算する場合、減算器が必要です。場合によっては、比較器も必要かも知れません。1の補数表示と2の補数表示は似ていますが、0が2通りで表示する1の補数表示は良くないように思えます。2の補数表示は、減算をする場合、加算器が使えます。ただし、2の補数への変換が必要です。

減算の場合、

表現方法 減算に必要なもの
絶対値表示 減算器
2の補数表示 加算器 ビット反転+1

となります。じつは、減算器よりはビット操作の方がずっと簡単です。そのような理由から、2の補数表現が使われるようになったのです。負の数の加算は、圧倒的に2の補数表示の方が簡単です。このような理由から、回路構成の簡単な2の補数の表現が使われるようになりました。単に、補数といえば2の補数と考えてください。

この方法で負の数を表すことは、1970年頃には常識となったようです。コンピューターの発明から20~30年も要したことを考えると、これに到達するまでに、技術者はかなりの試行錯誤を行ったと思います。

驚いたことに、負の数をこの補数で表すアイディアは、パスカルが最初です。パスカルは、パスカリーヌという歯車式計算機を1642年に製作しています。減算、あるいは負の数の加算を加算器(歯車)で行うために、補数というものを考えたようです。

ビット反転と+1加算の意味

正の整数 x として、-x を計算機の内部で表現する場合、

  1. xをビット反転する。
  2. +1加算する。

の操作を行いました。式で表すと,

\begin{align} [-x]=(FF-x+1)_{16}\label{eq:-x内部表現} \end{align}

でしたよね。ここでは、この操作の意味を調べます。結論から言うと、この操作は、符号反転の操作 (-1乗算) です。それでは、もう一回この操作を繰り返しましょう。すると

\begin{align} (FF-(FF-x+1)+1)_{16}&=(x)_{16} \nonumber\\ &=[x]\label{eq:符号反転} \end{align}

となります。このことから、この操作は、符号反転であることが分かります。式\eqref{eq:-x内部表現}は、xの符号反転を示しており、式\eqref{eq:符号反転}は-xの符号反転を示しています。

-x のコンピューター内部表現を求める式は、式\eqref{eq:-x内部表現}です。したがって、元の x を求めるためには、式\eqref{eq:-x内部表現}の反対の演算をすればよく、

  1. 1減算 (-1加算) する。
  2. ビットを反転する。

となります。式で表すと、

\begin{align} (FF-(FF-x+1-1))_{16}&=(x)_{16} \nonumber\\ &=[x]\label{eq:再び符号反転} \end{align}

です。しかし、元の表現を得るためには、式\eqref{eq:符号反転}の演算でも良いはずです。式\eqref{eq:再び符号反転}を変形すると式\eqref{eq:符号反転}が容易に導くことが出来ます。これらのことから、以下の結論を導くことが出来ます。

  • (符号の反転),(+1 加算) の操作は、コンピューターの内部表現の符号反転である。
  • この符号の反転と反対の操作(1減算)と(符号反転)は、まったく同じ操作である。

練習問題 (2の補数)

8ビットで、以下の計算を実施してみよう。

  1. 次の負の10進数を補数で表現してみましょう。
    例 (-14)10 00001110 14の2進数表現
    11110001 ビット反転
    11110010 +1 加算
    Q1 (-18)10
  2. 次の2の補数表現を10進数に変換してみましょう。
    11101011
    11101010 1減算
    00010101 ビット反転
    16+4+1=21 10進数に変換
    -(21)10
    例の別解法 11101011
    00010100 ビット反転
    00010101 +1 加算
    16+4+1=21 10進数に変換
    -(21)10
    Q1 11001011
  3. 次の計算を、10進数の演算を、2の補数を使って計算してみましょう。
    Q1 21-14 Q2 14-21


no counter