2011年7月7日木曜日

[C/C++] マシンイプシロン

マシンイプシロンを求めるプログラム例

#include <stdio.h>

int main(void)
{
  double deps=1.0//Machine epsilon, type: double
  double dtmp;      //Working variable, type: double
  float feps=1.0;   //Machine epsilon, type: float
  float ftmp;       //Working variable, type: float

  //Compute machine epsilon of type double
  //During dtmp = deps + 1.0, divide dtmp by 2

  for(dtmp = deps + 1.0; dtmp > 1; deps /= 2.0, dtmp = deps + 1.0);
  printf("Machine Epsilon of type double is %-16g\n", 2.0*deps);
  printf("Unit roundoff of type double is %-16g\n", deps);

  //Compute machine epsilon of type float
  //During ftmp + 1 > 1, divide ftmp by 2

  for(ftmp = feps + 1.0; ftmp > 1; feps /= 2.0, ftmp = feps + 1.0);
  printf("Machine Epsilon of type float is %-16g\n", 2.0*feps);
  printf("Unit roundoff of type float is %-16g\n", feps);

  return 0;

}

上記のプログラムをコンパイル,実行すると以下のようになります.
Machine Epsilon of type double is 2.22045e-16     
Unit roundoff of type double is 1.11022e-16     
Machine Epsilon of type float is 1.19209e-07     
Unit roundoff of type float is 5.96046e-08     

2011年7月2日土曜日

[C/C++] 倍精度型浮動小数点数フォーマットを出力

キーボードから入力された数の倍精度型浮動小数点フォーマットを出力するプログラム例を以下に示します.

#include <stdio.h>
#include <string.h>

int main(void)
{
  double a;
  char c[sizeof(a)];  // The data size of char type is 1 byte.
  int i, j, k;

  printf("Please input a number ---> ");
  scanf("%lf", &a);

  memcpy(c, &a, sizeof(a)); // Copy the contents of a to array c.

  printf("sEEEEEEE EEEEdddd dddddddd... \n");

  for( i = sizeof(a) - 1 ; i >= 0; i--)
  {
    for ( j = sizeof(c[i]) * 8 - 1; j >= 0; j--)
    {
      k = c[i] & (1 << j); //Logically multiply j by one by one.
      printf("%d", k ? 1 : 0); //If k = 0, 1 is displayed. 0 is displayed if k = 0.
    }
    printf(" ");
  }
  printf("\n");

  return 0;

}

実行結果は以下のようになります.
Please input a number ---> 777
sEEEEEEE EEEEdddd dddddddd... 
01000000 10001000 01001000 00000000 00000000 00000000 00000000 00000000 

上記のプログラムでは,1バイトごとにビット演算を行うため,char型の配列を用意しています(char型のデータサイズは1バイト,int型のデータサイズは4バイト).
文字配列 c の各要素 c[i] のサイズは1バイトなので,64ビットの倍精度型変数を格納するには c の配列サイズを8とする必要があります.
ここでは,sizeof関数を使って配列サイズをsizeof(a)=8としています.

memcpy関数は,メモリに格納されている内容をコピーするための関数で,例えばmemcpy(a, b, n)とすると,バッファbのnバイトの内容をバッファaにコピーします.
aとbには領域の先頭アドレスが入ります.
プログラムでは,データサイズが8バイトであるdouble型変数aの内容を文字配列cにコピーするために,aの先頭アドレス&a,配列cの先頭アドレスcおよびデータサイズsizeof(a)=8をmemcpy関数の実引数としています.