What is it, naokirin?

浮動小数点数

Write Portable Code」という複数のプラットフォームに移植可能なソフトウェアを書くにはどうすればよいかという本を読んだ。(もちろん、まだ読み終わっていない)
基本的C/C++についての事柄を中心に書かれている。ただしJavaなどの言語であっても、移植性問題が発生することは念頭に置くべき、とも書いてある。


今日読んだ第6章には浮動小数点数の移植性の問題が書かれている。

まず比較テストにおいて、プログラム上での計算過程(正確にはプログラムの書きかたの差異により、使われる命令セットが異なり、その時に精度が落ちたりするため)やコンパイラの最適化の有無によって、浮動小数点数は精度が変わることがあり、浮動小数点比較するときにはこれらが重要な問題となることもある。

また、浮動小数点数の丸めモードはC/C++はデフォルトで0に近い値に丸めるとなっている。しかし、CPUには4つの丸めモードが存在し、デフォルトでは一番近い値に丸めることになっていることが多い。
そのため、C/C++ではプログラマ側では見えないものの、丸めを行うような変換(浮動小数点数から整数への変換など)の場合は、コンパイラがCPUにモードの変更を行うコードを生成している。そのコードの中には、浮動小数点演算ユニット全体をフラッシュし、その結果FPUのパイプラインが一時中断するというような命令もある。
現実的に近年のプロセッサの処理能力なら問題なさそうに思えるが、非力なプロセッサや大量にキャストを行うとなるとかなりの問題になるはずである。

さらに整数と浮動小数点数C/C++ではそれぞれの型は非互換性である、ということとコンパイラによっては、エイリアス(別名)がないという仮定に基づいて積極的な最適化がおこなわれてしまうという問題もある。
たとえば本に載っている例だが

float f;
int x;
f = 1.0f;
x = * (int *) &f;

このような場合にコンパイラは「xは完全にfから独立している」と解釈するのである。もちろんそれは標準でint型とfloat型の互換性がないからである。


このように浮動小数点数の移植には様々な問題がある。
実際に浮動小数点数を正確に使わなければならない場合、プログラマ側が浮動小数点数の扱いについて十分に注意する必要があるようだ。