問題。
Microsoft Visual C ++ 2005コンパイラ、32ビットWindows XP SP3、AMD 64 X2 CPU
コード:
double a = 3015.0;
double b = 0.00025298219406977296;
//*((unsigned __int64*)(&a)) == 0x40a78e0000000000
//*((unsigned __int64*)(&b)) == 0x3f30945640000000
double f = a/b;//3015/0.00025298219406977296;
計算結果(つまり「f」)は11917835.000000000(((unsigned __int64)(&f))== 0x4166bb4160000000)ですが、11917834.814763514(つまり((unsigned __int64)(&f))== 0x4166bb415a128aef)である必要があります。
つまり、小数部分が失われます。
残念ながら、正確にするために小数部分が必要です。
質問:
1)なぜこれが起こるのですか?
2)どうすれば問題を解決できますか?
追加情報:
0)結果は「ウォッチ」ウィンドウから直接取得されます(印刷されなかったため、印刷精度を設定することを忘れませんでした)。浮動小数点変数の16進ダンプも提供したので、計算結果は間違いありません。
1)f = a/bの分解は次のとおりです。
fld qword ptr [a]
fdiv qword ptr [b]
fstp qword ptr [f]
2)f = 3015 / 0.00025298219406977296; 正しい結果が得られます(f == 11917834.814763514、((unsigned __int64)(&f))== 0x4166bb415a128aef)が、この場合、結果はコンパイル時に単純に計算されるように見えます。
fld qword ptr [__real@4166bb415a128aef (828EA0h)]
fstp qword ptr [f]
では、どうすればこの問題を解決できますか?
PS一時的な回避策を見つけました(除算の小数部分のみが必要なので、現時点ではf = fmod(a / b)/ bを使用しています)が、この問題を適切に修正する方法を知りたいです-倍精度は小数点以下16桁であると想定されているため、このような計算で問題が発生することはありません。