演習 (12/13)

今日のコンピュータで情報を処理するためには,その情報をまずビットの列として表現してメモリ上に格納する必要がある. 本日の演習のテーマは,メモリ上でデータがどのように配置されているかを観察することである.

整数

C言語で扱う整数のビット表現を知りたい場合,printf のフォーマット指定に %x を用いるとよい. printf で %x を指定すると,メモリ上のビット列を2進数とみなし,それを16進表記で出力する(「メモリ上のビット列が表す整数を16進数表記で出力する」ではない点に注意).

たとえば,次のプログラムにより,10進数の100と-1がメモリ上でどのようなビット列により表現されているかを調べることができる. なお,%x ではなく %08x としたのは,必要なら0を補い16進8桁で出力するように指定するためである.

#include <stdio.h>

int main (int argc, const char * argv[]) {
  int x = 100;
  int y = -1;
  printf("x = %08x\n", x);
  printf("y = %08x\n", y);
  return 0;
}

上と同様のプログラムを64ビットの整数を対象に定義すると次のようになる. int を long long int に置き換えることにより,x, y それぞれのために,メモリ上には32ビットではなく64ビットの領域が確保される. 100, -1 の末尾の LL は,これらが64ビットの整数値であることを明示的に表すために追加されている. さらに,printf では %08x ではなく %016llx を指定する(数字の1と小文字のlが紛らわしいので注意).

#include <stdio.h>

int main (int argc, const char * argv[]) {
  long long int x = 100LL;
  long long int y = -1LL;
  printf("x = %016llx\n", x);
  printf("y = %016llx\n", y);
  return 0;
}
作業1

上の2つのプログラムを実行し,出力結果を確認せよ.

レポート課題1 (12/20 締切)

負数を含む整数を表現する方法の概略は,10月11日の配布資料の26ページ目で説明した. 上の2つのプログラムを参考に,32ビットの整数がどのようなビット列で表現されているかを調べて報告せよ. 最低でも,0, 絶対値が小さい正負の整数,絶対値が大きい正負の整数について確認すること.

参考のため,1桁の16進数と4桁の2進数の対応表を掲載する.

16進2進16進2進
0000081000
1000191001
20010a1010
30011b1011
40100c1100
50101d1101
60110e1110
70111f1111

浮動小数点数

実数(一般的には小数点以下無限桁の数)を近似値に扱うために、IEEE 754 形式の浮動小数点数が用いられることが多い. 演習室で C 言語を用いて浮動小数点数の計算を行う時にも,基本的に IEEE 754 形式が使われる.

次のプログラムは,32ビットの浮動小数点数xのビット表現を16進表記で出力する. ここでは,x が32ビットの浮動小数点数を表す float 型の変数として宣言されている. 浮動小数点数のビット表現を16進表記で出力するためには少し細工が必要で,*(int *)& の部分でその調整を行っている(ただし、この方法が必ずうまくいく保証はない). 詳しくは述べないが,*(int *)&x は,x と同じビット表現をもった整数を表す.

#include <stdio.h>

int main (int argc, const char * argv[]) {
  float x = 0.0;
  printf("x = %08x\n", *(int *)&x);
  return 0;
}

IEEE 754 形式でも,すべてのビットが 0 となるビット列で値としての 0 を表す. ただし,整数の標準的な表現方法と異なり,IEEE 754 形式では +0.0 と -0.0 が異なるビット表現になる.

作業2

上のプログラムを実行し,00000000 が出力されることを確認せよ(実行の仕方によっては異なる結果が出るかもしれない). また,0.0 を -0.0 で置き換えるとどうなるか確認せよ.

IEEE 754 形式では,無限大,非数などの特殊な値も表現できるが,ここでは触れないことにする. 普通の正負の小数点数(0 は除く)を表すには,その数をまず ± (1 + F) × 2(E - 127) (0.0 ≤ F < 1.0, E は整数で 1 ≤ E ≤ 254)のような形に正規化する. この範囲に収まらない数は対象から除外する. そして,± に1ビット,F に23ビット,E に8ビットの合計32ビットを割り当てる. なお,F を表現するビット列を仮数部,E を表現するビット列を指数部と呼ぶ.

レポート課題2 (12/20 締切)

上のプログラムの x の値をいろいろ変えてみると,さまざま小数点数(整数も含む)がどのようなビット列で表現されるかを知ることができる. そこで以下のような観察と考察を行え.

  1. 同じ絶対値の正負の値の対(たとえば 1.0 と -1.0)に対して,それらのビット表現のどこがどのように異なるかを観察せよ. 複数の対に対してこの観察を行い,± をどのように表現しているかを推測せよ.
  2. ある値と2倍(あるいは2n倍)異なる別の値のビット表現を比較し,どこがどのように異なるか観察せよ. 複数の対に対してこの観察を行い,指数部がどのように表現されているかを推測せよ.
  3. 仮数部についても同様の観察と推測を行え.