C ++浮動小数点精度の損失:3015 / 0.00025298219406977296
-
22-09-2019 - |
質問
問題ます。
のMicrosoft Visual C ++ 2005コンパイラ、32ビットのWindows XP SP3は、64×2 CPUをamdの。
コード:
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(((符号なし__int64 )(&F))== 0x4166bb4160000000)は11917834.814763514(すなわち、((符号なし__int64されるべきですの)(&F))== 0x4166bb415a128aef)。
即ち小数部分が失われる。
残念ながら、私は正しいと小数部を必要としています。
質問:
1)これはなぜ起こるのでしょうか?
2)どのように私は問題を解決することができますか?
追加情報:
0)の結果は、の直接の「ウォッチ」ウィンドウ(それが印刷されていなかった、と私はセットの印刷精度を忘れなかった)から取られています。私は、計算結果について絶対に確信しているので、私はまた、浮動小数点変数の進ダンプを提供する。
1)分解のF = A / Bである:
fld qword ptr [a]
fdiv qword ptr [b]
fstp qword ptr [f]
2)、F = 3015 / 0.00025298219406977296。利回り正しい結果(F == 11917834.814763514、の((符号なし__int64 の)(&F))== 0x4166bb415a128aef)が、それはこの場合、結果には、単にコンパイル時中に計算されるようになります。
fld qword ptr [__real@4166bb415a128aef (828EA0h)]
fstp qword ptr [f]
だから、どのように私はこの問題を解決することができますか?
P.S。私は(私は単に現時点で= FMOD(/ B)/ B fを使うので、私は、除算の小数部だけを必要とする)一時的な回避策を見つけたが、私はまだきちんとこの問題を解決する方法を知っていただきたいと思います - ダブルこのような計算が原因の問題に想定されていないので精度は、16桁であると考えられる。
解決
あなたはあなたのプログラムの任意の場所でのDirectXを使用しています
他のヒント
興味深いことに、あなたは正確に11917835.000000000を取得します。私の推測では、計算の定数がどのように解釈されるかで以降のいずれかで、どこかに起こっ単精度への変換があるということですので。
いずれの場合も、あなたのコードがどのようにシンプル考えると、少しはしかし、驚くべきことです。あなたは、すべての浮動小数点数のための単一の精度を強制的に、任意のエキゾチックなコンパイラディレクティブを使用していない?
編集:あなたが実際にコンパイルされたプログラムが不正な結果を生成することを確認したことがありますか?そうでない場合は、(誤)単精度変換のための最も可能性の高い候補はデバッガであろう。
あなたは正確な数学が必要な場合は、浮動小数点を使用しないでください。の
自分に好意を行うと有理数をサポートしたBIGNUMライブラリを取得します。
私はあなたが精度を指定せずに番号をプリントアウトしていると思うだろう。これを試してください:
#include <iostream>
#include <iomanip>
int main() {
double a = 3015.0;
double b = 0.00025298219406977296;
double f = a/b;
std::cout << std::fixed << std::setprecision(15) << f << std::endl;
return 0;
}
このは生成します:
11917834.814763514000000
私には正しく見える。私はVC ++ 2008の代わりに2005を使用していますが、私は違いがあなたのコードではなく、コンパイラであると思い思います。
あなたは確かにあなたはFSTP命令の後にF右の値を調べていていますか?あなたはおそらく、ウォッチウィンドウは、いくつかの後の時点で撮影した値を示すことができオン最適化を持っていれば(これはあなたが後でFの端数部分を見ていると言うように、ビットもっともらしいと思われる - それをマスキングするまで、いくつかの命令の風を行いますアウト何とか?)