私のアルゴリズムは、単精度浮動小数点演算のイプシロンを計算しています。1.1921e-007前後のはずです。コードは次のとおりです。
static void Main(string[] args) {
// start with some small magic number
float a = 0.000000000000000013877787807814457f;
for (; ; ) {
// add the small a to 1
float temp = 1f + a;
// break, if a + 1 really is > '1'
if (temp - 1f != 0f) break;
// otherwise a is too small -> increase it
a *= 2f;
Console.Out.WriteLine("current increment: " + a);
}
Console.Out.WriteLine("Found epsilon: " + a);
Console.ReadKey();
}
デバッグモードでは、次の妥当な出力(省略形)が得られます。
current increment: 2,775558E-17
current increment: 5,551115E-17
...
current increment: 2,980232E-08
current increment: 5,960464E-08
current increment: 1,192093E-07
Found epsilon: 1,192093E-07
ただし、リリースモードに切り替えると(最適化の有無に関係なく!)、コードは次の結果をもたらします。
current increment: 2,775558E-17
current increment: 5,551115E-17
current increment: 1,110223E-16
current increment: 2,220446E-16
Found epsilon: 2,220446E-16
これは倍精度の値に対応します。したがって、いくつかの最適化により、計算がdouble値で実行されると思います。もちろん、この場合の結果は間違っています!
また、これは、プロジェクトオプションでX86リリースをターゲットにしている場合にのみ発生します。繰り返しますが、最適化のオン/オフは重要ではありません。私は64ビットWIN7、VS 2010 Ultimateを使用しており、.NET4.0をターゲットにしています。
何がその振る舞いを引き起こす可能性がありますか?いくつかのWOWの問題?信頼できる方法でそれを回避する方法は?単精度計算の代わりに倍精度を使用するコードをCLRが生成しないようにするにはどうすればよいですか?
注:ここで問題が発生しなくても、プラットフォームターゲットとして「AnyCPU」または「X64」に切り替えることはできません。ただし、32/64ビット用のさまざまなバージョンのネイティブライブラリがいくつかあります。したがって、ターゲットは具体的でなければなりません。