ouble の計算結果が状況によっておかしくなる場合があるのですが、
理由がなかなか分からないので心当たりがあれば教えてもらえませんか。
問題のコードを簡略化したのが以下です。
------------------------------------
void calc(double *result) {
const double mPI2 = 1.5707963267948966;
double b_arc;
b_arc の計算 … (1)
// printf("test"); … (2)
*result = mPI2 - b_arc; … (3)
}
------------------------------------
おかしくなるのは(3)の *result の値です。
(3)での b_arc、mPI2 の値を出力してみると
b_arc: [1.57079632679489660000000000000000000000]
mPI2: [1.57079632679489660000000000000000000000]
となり、mPI2 == b_arc の結果も true になります。
さらに、バイナリで見ても二つは全く同じ値でした。
なので *result は 0 になるはずなのですが、これが 0 にならない場合があります。
色々な状態で試したところ結果は以下のようになりました。
1. Windows7 : 0
2. WindowsXP : -0.000000000000000001951563910473908
3. WindowsXPのデバッグビルド : 0
4. WindowsXPで(2)(2)のコメントアウトを外し printf をいれる : 0
WindowsXPのリリースビルドだけ 0 にならず、 -0.000000000000000001951563910473908 になります。
4は理由が分からないのですが、(2)の位置になんらかの処理をいれると結果が 0 になります。
ちなみにVC++ではなくQTというFrameworkを使って作っています。
よろしくお願いします。
No.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となっている、というのが理由だと思います。
どうもありがとうございます。
リンクも参考になりました。
No1の方も同じことをおっしゃっていますし、
その可能性が高いということで対応していこうと思います。
No.2
- 回答日時:
余談ですが「VC++ではなくQTというFrameworkを使って作っています」といわれてもねぇ.
コンパイラを確定させてほしい....
No.1
- 回答日時:
憶測ですが……。
b_arc の計算で、三角関数の計算があるとして、
b_arc に結果が代入される直前の、拡張精度(double より、さらに桁数の多い計算、計算の中間で使われることはある)の変数を、最適化の結果として、*result への代入に使っているのではないかなという気はします。
だから、result への代入の前に別の処理が入ると、この最適化ができずに、b_arc の値をまじめに使って計算しているとか。
アセンブラに落ちた結果を確認すると良いですが。
もしくは、リリースビルドの最適化をOFFにして結果がどう変わるか確認してみるとか。
回答ありがとうございます。
確かにそれだと何か処理をいれると値が変わることに説明がつきますね。
ネットで調べてみたのですが、アセンブラは値が見れませんでした。
全然アセンブラの知識がないので調べるのはちょっと時間がかかりそうです。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
-
誕生日にもらった意外なもの
みなさんがもらった誕生日プレゼントで面白いものがあったらぜひ教えてください!
-
フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
あなたが普段思っている「これまだ誰も言ってなかったけど共感されるだろうな」というあるあるを教えてください
-
映画のエンドロール観る派?観ない派?
映画が終わった後、すぐに席を立って帰る方もちらほら見かけます。皆さんはエンドロールの最後まで観ていきますか?
-
海外旅行から帰ってきたら、まず何を食べる?
帰国して1番食べたくなるもの、食べたくなるだろうなと思うもの、皆さんはありますか?
-
天使と悪魔選手権
悪魔がこんなささやきをしていたら、天使のあなたはなんと言って止めますか?
-
doubleの変数にintとintの割り算の結果を代入するとき
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
c languageで 簡単な質問があ...
-
VB.net Double と...
-
VBAでミリ秒まで出力する方法
-
位相の有効数字
-
ExcelでPC(パソコン)によって...
-
VB6.0での小数点の扱いについて
-
除算を使わずに10で割りたい。
-
【C言語】RGBと輝度の計算に関して
-
16進数 加算 減算 C言語
-
任意の桁数を表示するには?
-
2038年問題 日付算出
-
計算の丸め誤差の解消について
-
三角比の俯角の計算
-
double型からfloat型への型変換...
-
三菱シーケンサ(Aシリーズ)で...
-
EXCELの関数"STDEV(標準偏差)"...
-
C言語プログラミングにて、arct...
-
エクセルの多い桁数を表示させ...
-
扱える数字の最大値
-
Double型について
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
O(n log n)について2
-
VB.net Double と...
-
c languageで 簡単な質問があ...
-
ExcelのINT関数の計算結果がお...
-
有効数字について 以前質問をし...
-
ExcelでPC(パソコン)によって...
-
三菱シーケンサ(Aシリーズ)で...
-
除算を使わずに10で割りたい。
-
16進数 加算 減算 C言語
-
EXCELの関数"STDEV(標準偏差)"...
-
VB6.0での小数点の扱いについて
-
”/”を使わずに割り算したいんで...
-
距離から緯度経度を求める方法
-
VBAでミリ秒まで出力する方法
-
floatの有効桁数
-
コンピューターは指数関数をど...
-
時刻の比較
-
計算の丸め誤差の解消について
-
Double型について
-
powf を使わずにべき乗を計算
おすすめ情報