• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:浮動小数演算での誤差の蓄積が起こっているのかどうか)

浮動小数演算での誤差の蓄積が起こっているのかどうか

このQ&Aのポイント
  • C++でプログラミングの勉強をしています。ある実数演算(double)をする関数A(実数パラメータxを用いた積算)を2種類の方法で用いると、結果が微妙に変わってしまいます。条件は同じなので、同じ結果が出て欲しいのですが、結果が変わってしまい困っています。原因としては何が考えられるでしょうか?
  • ループ中に共有している変数は必ず初期化しているのに、前のパラメータの時の実数演算の誤差が積み重なっている可能性はありますか?ソースコードは複雑なため、載せることはできません。原因として考えられることを教えて頂けると助かります。
  • 悩んでいる現象は、パラメータxを微小に変化させながら関数Aをfor文でループさせ、最後の結果を入手する方法と、パラメータxの大きさを同じにして関数Aを1回のみ用いて結果を入手する方法で、微妙に結果が変わる点です。条件は同じだと思うので、なぜ結果が異なるのかがわかりません。どんなことが考えられる原因でしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

パラメータをたとえば0→1の間で10000分割した場合、 forループで1万回0.0001を加算して最後に1になった場合 の結果を出していれば、誤差で一致しない可能性があると思います。 0.0001×10000でも誤差が出るでしょう。 今思いついたのはその位です。

tokkotokon
質問者

お礼

無事同じ結果が出ました. やはり,実数を何回も足していたのが原因でした. 私の些細なミスに対して,時間を割いてまで回答して頂きありがとうございました. doradora55さんの欄にて回答して頂いた皆様にお礼を申し上げます.

tokkotokon
質問者

補足

回答の通りかもしれません. (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

その他の回答 (4)

  • ki073
  • ベストアンサー率77% (491/634)
回答No.5

シミュレーションソフトを動かしていて計算式自体が同じソースコードなのに結果が微妙に違うことがあります。 今把握している(想像している?)原因としては (1) 同じソースコードなのに、ループの中などに存在すると、コンパイラの最適化で式の順序が入れ替えられ、数学の式としては等価ですが、小数点誤差の蓄積され方が異なる。 (2) 割り算を高速化するために、逆数に変換してからかけ算をするように最適化されることもあります。直接割り算よりも速いですが、誤差が大きくなります。 (3) コンパイルするときにIEEE 754に完全には準拠していない演算になっていることが多いです。丸め誤差などが微妙に違うようです。 コンパイラの最適化なし(オプション-O0が多いです)でやってみたらどうですか?(1)と(2)はこれで避けられるはず。 (3)は別にオプションがあるかもしれませんし、-O0でIEEE754に準拠されるかは分かりません。私が使っているPGIコンパイラは別にあります。 普通の計算では目立たないのですが、このようなことがあると何万回も加算をすると差が出ます。

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.4

0,01を25回足すのは、毎回、真の0.01との誤差が加わるので、誤差が蓄積されやすいです。 大使、25 * 0.01だと、真の0.01と0.01との誤差はこの時点では最小だし、かけ算は一時的により大きな桁で計算して結果をまるめる形になるので、誤差は小さくてすみます。 有限桁の2進浮動小数点を使った数値演算ではいろんなところで誤差が出るので、精度よく計算したいなら常に考えておく必要があります。

  • wormhole
  • ベストアンサー率28% (1626/5665)
回答No.3

最終的には同じ結果になるはずのものでも 浮動小数点演算があってその手順が異なるのであれば 演算誤差に差異があるのは当然かと思いますが。 そういう場合は許容誤差いくらかまでは同じとみなすとかするんじゃないかなぁ。 doubleやfloatが保持できるのは近似値というのは理解されていますよね?

tokkotokon
質問者

補足

近似値になると言うのはもちろん理解しています. ただ,(1)は独立した関数Aをループさせているはずなので, 演算誤差も同じ値が出るのではないのですか? ループ内の関数Aの演算が次のパラメータの際に影響するなら, 演算誤差は違う値になるのではないのかと思います. 違っていたら申し訳ございません.

  • ki073
  • ベストアンサー率77% (491/634)
回答No.2

整数は2進数で正確に表せるが、小数部分は正確に表せないものがあるからです。 例えば、0.1は2進数でどう表すか調べてみてください。それを10倍してみてください。 浮動小数点をイコールで比較すると問題がでるのもそのためです。