![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?e8efa67)
C++でプログラミングの勉強をしています.
以下の現象で悩んでいます.
ある実数演算(double)をする関数A(実数パラメータxを用いた積算)を
以下の2種類の方法で用いると,結果が微妙に変わってしまいます.
(1)パラメータxを微小に変化させながら,関数Aをfor文でループさせ,最後の結果を入手する.
(xを変化させても,Aの結果が変わらないようにその他の変数を初期化しているのですが・・・)
(2) (1)の最終条件(パラメータxの大きさ)を同じにして,関数Aを1回のみ用いて,結果を入手する.
条件は同じはずなので,同じ結果が出て欲しいのですが,
結果が変わってしまい困っています.
この場合考えられる原因としては何があるでしょうか?
・前のパラメータの時の実数演算の誤差が積み重なっている可能性はありますか?
(でも,ループ中に共有している変数は必ず初期化しているのですが・・・)
ソースコードは複雑なため,載せることはできません.
大変申し訳ございません.
原因としてどんなことが考えられるのかを教えて頂けると助かります.
宜しくお願い致します.
No.1ベストアンサー
- 回答日時:
パラメータをたとえば0→1の間で10000分割した場合、
forループで1万回0.0001を加算して最後に1になった場合
の結果を出していれば、誤差で一致しない可能性があると思います。
0.0001×10000でも誤差が出るでしょう。
今思いついたのはその位です。
この回答への補足
回答の通りかもしれません.
(1)はパラメータxを0.01刻みでループさせています.
例えば
「xを0.25まで加算させた際の結果」と
「xに0.25を代入した際の結果」では違う値になっている可能性があります.
それならば,ループの際に0.01加算するのではなく,
「x(整数型にしておく)に1加算して,100で割る」
という方法で対処できますか?
つまり,0.01ずつ加算して0.25を表現する(A式)のではなく,
B式でやれば誤差は生じないでしょうか?
A式:y(実数) = x(実数) + 0.01で
B式:y(実数) = ( x(整数) + 1 ) / 100
無事同じ結果が出ました.
やはり,実数を何回も足していたのが原因でした.
私の些細なミスに対して,時間を割いてまで回答して頂きありがとうございました.
doradora55さんの欄にて回答して頂いた皆様にお礼を申し上げます.
No.5
- 回答日時:
シミュレーションソフトを動かしていて計算式自体が同じソースコードなのに結果が微妙に違うことがあります。
今把握している(想像している?)原因としては
(1) 同じソースコードなのに、ループの中などに存在すると、コンパイラの最適化で式の順序が入れ替えられ、数学の式としては等価ですが、小数点誤差の蓄積され方が異なる。
(2) 割り算を高速化するために、逆数に変換してからかけ算をするように最適化されることもあります。直接割り算よりも速いですが、誤差が大きくなります。
(3) コンパイルするときにIEEE 754に完全には準拠していない演算になっていることが多いです。丸め誤差などが微妙に違うようです。
コンパイラの最適化なし(オプション-O0が多いです)でやってみたらどうですか?(1)と(2)はこれで避けられるはず。
(3)は別にオプションがあるかもしれませんし、-O0でIEEE754に準拠されるかは分かりません。私が使っているPGIコンパイラは別にあります。
普通の計算では目立たないのですが、このようなことがあると何万回も加算をすると差が出ます。
No.4
- 回答日時:
0,01を25回足すのは、毎回、真の0.01との誤差が加わるので、誤差が蓄積されやすいです。
大使、25 * 0.01だと、真の0.01と0.01との誤差はこの時点では最小だし、かけ算は一時的により大きな桁で計算して結果をまるめる形になるので、誤差は小さくてすみます。
有限桁の2進浮動小数点を使った数値演算ではいろんなところで誤差が出るので、精度よく計算したいなら常に考えておく必要があります。
No.3
- 回答日時:
最終的には同じ結果になるはずのものでも
浮動小数点演算があってその手順が異なるのであれば
演算誤差に差異があるのは当然かと思いますが。
そういう場合は許容誤差いくらかまでは同じとみなすとかするんじゃないかなぁ。
doubleやfloatが保持できるのは近似値というのは理解されていますよね?
この回答への補足
近似値になると言うのはもちろん理解しています.
ただ,(1)は独立した関数Aをループさせているはずなので,
演算誤差も同じ値が出るのではないのですか?
ループ内の関数Aの演算が次のパラメータの際に影響するなら,
演算誤差は違う値になるのではないのかと思います.
違っていたら申し訳ございません.
No.2
- 回答日時:
整数は2進数で正確に表せるが、小数部分は正確に表せないものがあるからです。
例えば、0.1は2進数でどう表すか調べてみてください。それを10倍してみてください。
浮動小数点をイコールで比較すると問題がでるのもそのためです。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Chrome(クローム) Chromeの描画領域を2分割して異なるスクロール位置を同時に表示させることはできますか 1 2023/03/01 16:53
- Visual Basic(VBA) Excel のユーザー定義関数でソルバーが動作しない 1 2022/09/05 19:51
- 数学 モデルのパラメータの定義がいまいちわかりません。 3 2022/10/11 15:16
- Excel(エクセル) エクセルのSUM関数について 4 2023/04/18 10:37
- その他(プログラミング・Web制作) pythonのmap、結果の利用は1度だけ? 5 2022/06/11 12:33
- その他(プログラミング・Web制作) パイソンのプログラミングについての質問です 2 2023/05/22 12:39
- 物理学 『数か物か』 4 2022/06/13 06:54
- C言語・C++・C# C言語 3 2022/10/04 15:07
- 統計学 回帰分析検証不一致 5 2022/05/04 20:48
- Visual Basic(VBA) VBAで時間(00:00形式)を積算(足し算)したい 1 2022/11/15 17:04
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
O(n log n)について2
-
C言語 型変換のタイミング
-
Log関数に関する質問
-
有効数字について 以前質問をし...
-
CRCの計算方法について
-
c languageで 簡単な質問があ...
-
Pythonについてなのですが、小...
-
距離から緯度経度を求める方法
-
VBAでの割り算の余りの求め方
-
最大50桁の実数の和・差・積を...
-
三菱シーケンサ(Aシリーズ)で...
-
C言語について。
-
信頼区間の1.96や1.65ってどこ...
-
2÷3などの余りについて
-
大学数学の問題です。 加法群Z/...
-
#define _CRT_SECURE_NO_WARNIN...
-
教えてください。数学Bの二項分...
-
「Aに対するBの割合」と「Aに対...
-
EXCELの分散分析表のP-値が....
-
Enterキーを押されたら次の処理...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
O(n log n)について2
-
16進数 加算 減算 C言語
-
c languageで 簡単な質問があ...
-
VB.net Double と...
-
”/”を使わずに割り算したいんで...
-
三菱シーケンサ(Aシリーズ)で...
-
ExcelのINT関数の計算結果がお...
-
有効数字について 以前質問をし...
-
ExcelでPC(パソコン)によって...
-
除算を使わずに10で割りたい。
-
EXCELの関数"STDEV(標準偏差)"...
-
floatの有効桁数
-
VBAでミリ秒まで出力する方法
-
100桁の計算ができなくて困って...
-
2進数の足し算(C言語)
-
VB6.0での小数点の扱いについて
-
VBAでの割り算の余りの求め方
-
コンピューターは指数関数をど...
-
距離から緯度経度を求める方法
-
BCD・HEX・BINについて
おすすめ情報