- ベストアンサー
【C++】double の計算結果がおかしくなる
- double型の計算結果が状況によっておかしくなる問題について質問します。
- 具体的なコード例を示しながら、問題の原因やバグについての情報を教えてください。
- Windows環境上での現象やその他状況についても詳しく教えていただけると助かります。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
おそらく、下記リンクにあるような浮動小数用レジスタの扱いが原因だと思います。 http://0xcc.net/blog/archives/000164.html doubleはメモリ上では64bitですが、実際にプロセッサ内で計算する場合には、モードや動作環境にもよりますが64bit以上のサイズのレジスタ(80bit)が使われることが多いようです。 したがって、レジスタにはいっている値をメモリに戻す時に精度の低下が発生します。 b_arc: [1.57079632679489660000000000000000000000] とありますが、プロセッサ内で浮動小数演算を連続して実行し続けている場合、レジスタ内ではもう少し値が入っており、 b_arc: [1.5707963267948966********] という感じになっているはずです。そこから mPI2: [1.57079632679489660000000000000000000000] を引くため、正しい計算結果としては 0.0000000000000000******** となり、この差分が > 2. WindowsXP : -0.000000000000000001951563910473908 では無いかと思います。 > 4は理由が分からないのですが、(2)の位置になんらかの処理をいれると結果が 0 になります。 というのは、途中で別の命令が入ってくるため浮動小数演算がいったん中断され、80bitレジスタの値を64bitのメモリにダウンコンバートしながら移動する、すなわちb_arcの値を [1.5707963267948966*****] → [1.57079632679489660000000000000000000000] と変換する処理が途中に入ってしまい、結果としてmPi2==b_arcとなっている、というのが理由だと思います。
その他の回答 (2)
- Tacosan
- ベストアンサー率23% (3656/15482)
余談ですが「VC++ではなくQTというFrameworkを使って作っています」といわれてもねぇ. コンパイラを確定させてほしい....
補足
コンパイラはGCC(MinGW)です。
- 麻野 なぎ(@AsanoNagi)
- ベストアンサー率45% (763/1670)
憶測ですが……。 b_arc の計算で、三角関数の計算があるとして、 b_arc に結果が代入される直前の、拡張精度(double より、さらに桁数の多い計算、計算の中間で使われることはある)の変数を、最適化の結果として、*result への代入に使っているのではないかなという気はします。 だから、result への代入の前に別の処理が入ると、この最適化ができずに、b_arc の値をまじめに使って計算しているとか。 アセンブラに落ちた結果を確認すると良いですが。 もしくは、リリースビルドの最適化をOFFにして結果がどう変わるか確認してみるとか。
お礼
回答ありがとうございます。 確かにそれだと何か処理をいれると値が変わることに説明がつきますね。 ネットで調べてみたのですが、アセンブラは値が見れませんでした。 全然アセンブラの知識がないので調べるのはちょっと時間がかかりそうです。
お礼
どうもありがとうございます。 リンクも参考になりました。 No1の方も同じことをおっしゃっていますし、 その可能性が高いということで対応していこうと思います。