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の値ひとつで,コンパイラが出力するバイナリの性質を制御することができる.