C99における浮動小数点演算の計算精度(その1)

C99では,FLT_EVAL_METHOD というラベルの値で,浮動小数点演算の計算精度が制御できる.

FLT_EVAL_METHODの値と保証される精度の関係は以下の表の様になる.

FLT_EVAL_METHODの値 float型が保証する精度 double型が保証する精度
0 float double
1 double double
2 long double long double
その他 未定義 未定義


この計算精度がどういう意味を持つかというと,たとえばFLT_EVAL_METHODが1に設定されている場合は

float a;
float b;
float c=a*b;

というソースは,コンパイラにより

float c=(double)a * (double)b;

というコードに変換される.(少なくともx86では) floatは仮数部24bit,doubleは仮数部53bit, long double は仮数部64bitの計算精度を持つので,a*bの演算は 53bit の精度で行われ,演算結果53bitの内24bit分の情報が,変数cの領域にストアされる.


一般的に,CPU(=FPU)の計算機アーキテクチャを考慮すると,

  • 乗算・除算の計算速度は精度が低い方が高速になる.(ただし,加算・減算の計算は,double(53bit) でも float(24bit) でも同じ回路を使うCPUがほとんどで,計算速度も同じになることが多い)
  • floatのほうが必要とするメモリ量が少ないため,キャッシュの恩恵を受けやすく高速である.

ことから計算精度と実行速度にはトレードオフの関係がある.

つまり,

  • FLT_EVAL_METHOD を 0 にしておくと精度を犠牲にして,実行速度を優先.
  • FLT_EVAL_METHOD を 2 にしておくと実行速度を犠牲にして,精度を優先.
  • FLT_EVAL_METHOD を 1 は,その中間.

という風に,FLT_EVAL_METHODの値ひとつで,コンパイラが出力するバイナリの性質を制御することができる.