2016/10/15改定

【変数の有効桁】

・天文計算の必要精度
多用すると思われるユリウス日で考える。

現在のユリウス日は、
 2 457 469 の7桁ある。
これに小数として時間が加わる。

1秒を日の小数に直すと
 0.000 011 574 074 074...
適当な桁で切って逆算
0.000 01    → 0.864
0.000 012   → 1.036 8
0.000 011 6 → 1.002 24

表示は四捨五入されるので、
小数以下5桁あれば元の1秒になる。
1秒精度を目指すなら
7桁+5桁の12桁あれば良い。

では、地球時の計算に使う
32.184s、これは
0.001s(1msec)単位である。
日の小数にすると
0.000 000 01157407...
小数以下8桁は必要。
1msecを目指すなら
7+8=15桁以上になります。

さらに、地心座標時では、
約6.97 × 10^-10(day)
= 0.000 000 000 697
これを秒にすると
0.000 06 = 60nsec(ナノ秒)
10nsecを目指すなら
7+10=17桁以上。

自分の目的に応じて
必要桁数が変わります。


・変数を調べる
C言語の変数を調べてみます。
下のソースは、
各変数のサイズ・
実数変数の最大値(絶対値)
の表示サンプルソースです。

コンパイルしてコンソールで実行します。
#include <stdio.h>
#include <float.h>

int main(void)
{
    printf("char = %ld\n", sizeof(char));
    printf("short int = %ld\n", sizeof(short int));
    printf("int = %ld\n", sizeof(int));
    printf("long int = %ld\n", sizeof(long int));
    printf("long long int = %ld\n", sizeof(long long int));
    printf("float = %ld\n", sizeof(float));
    printf("double = %ld\n", sizeof(double));
    printf("long double = %ld\n", sizeof(long double));
    printf("\n");

    printf("float = %e\n", FLT_MAX);
    printf("double = %le\n", DBL_MAX);
    printf("long double = %Le\n", LDBL_MAX);

    return 0;
}
※long long int、long double等でエラーなら
 サポートしていない可能性があります。

それぞれの環境での結果です。
WinXP(32bit)+VS2010 Linux(32bit)+gcc(4.7.1) Linux(64bit)+gcc(4.9.2)
char = 1
short int = 2
int = 4
long int = 4
long long int = 8
float = 4
double = 8
long double = 8

float = 3.402823e+038
double = 1.797693e+308
long double = 1.797693e+308
char = 1
short int = 2
int = 4
long int = 4
long long int = 8
float = 4
double = 8
long double = 12

float = 3.402823e+38
double = 1.797693e+308
long double = 1.189731e+4932
char = 1
short int = 2
int = 4
long int = 8
long long int = 8
float = 4
double = 8
long double = 16

float = 3.402823e+38
double = 1.797693e+308
long double = 1.189731e+4932
それぞれに微妙な違いがあるので、移植には注意が必要です。

・整数変数の有効桁を調べる
変数の10進数での有効桁数を調べます。

2進数のビット数がの 10進数の桁数は、



で計算できます。

例えば、4バイト整数(32bit)では
符号なし log(2^32)  ≈ 9.6 (0~4 294 967 295)
符号あり  log(2^31)  ≈ 9.3 (-2 147483 648~+2 147 483 647)

9桁までは全て表現できるが、
10桁目は一部しか表現できない。
という結果になります。

・実数変数の有効桁を調べる
実数は指数部と仮数部に別れており、
有効桁は仮数部のビット数で計算します。
仮数部のビット数を知るには、

仮数ビット数=全体ビット数 - 指数ビット数

という計算をします。

最初に指数のビット数を計算します。
変数の最大値(10進数)をとした時、
2 進数の指数は、



となります。

4バイト(32bit)floatの最大値は
 3.402823e+38 であるから、
log(3.402823e+38)÷Log2 ≈ 128
128(0x80)は8ビットなので、
指数は8bitだとわかる。

仮数部は32-8=24ビットとなる。
24ビットの有効桁は
log(2^24) ≈  7.2
結果7桁までで
8桁目は一部表示可能となる。

同様に計算した実数変数は、
4バイトfloat  指数8 仮数24  で 7桁
8バイトfloat  指数11仮数53  で 15桁
12バイトfloat 指数15仮数81  で 24桁
16バイトfloat 指数15仮数113 で 34桁

という結果になる。

以上から、
1msec精度なら double
それ以上なら long double
を使わないといけない。

inserted by FC2 system