効率を上げるために、いくつかのプログラムをMatlabからC ++に移植しています。両方のプログラムの出力が完全に同じであることが重要です(**)。
この操作で異なる結果に直面しています。
std::sin(0.497418836818383950) = 0.477158760259608410 (C++)
sin(0.497418836818383950) = 0.47715876025960846000 (Matlab)
N[Sin[0.497418836818383950], 20] = 0.477158760259608433 (Mathematica)
したがって、私が知る限り、C ++とMatlabの両方がIEEE754で定義された二重演算を使用しています。IEEE754では最後のビットで異なる結果が許可されていることをどこかで読んだと思います。数学を使って決定するのは、C ++の方が結果に近いようです。結果が同じになるように、Matlabに含まれる最後のビットまで正確にsinを計算させるにはどうすればよいですか?
私のプログラムでは、数値微分方程式ソルバーが最後のビットでこのエラーを増やし続けるため、この動作は大きなエラーにつながります。ただし、C ++で移植されたバージョンが正しいかどうかはわかりません。IEEE754で最後のビットの変更が許可されている場合でも、 IEEE754で定義されたdouble操作の結果を使用したときに、このエラーが大きくならないことが保証されていると思います(そうでない場合、IEEE754標準に従って正しい2つの異なるプログラムが生成される可能性があるため)完全に異なる出力)。だから他の質問は私はこれについて正しいですか?
両方の太字の質問に対する回答を取得したいと思います。編集:最初の質問はかなり物議を醸していますが、それほど重要ではありません、誰かが2番目の質問についてコメントできますか?
注:これは印刷のエラーではありません。確認したい場合に備えて、次のようにしてこれらの結果を取得しました。
http://i.imgur.com/cy5ToYy.png
注(**):これが意味するのは、小数点以下4桁の実数を示すいくつかの計算の結果である最終出力は、完全に同じである必要があるということです。私が質問で話しているエラーは大きくなります(操作が増えるため、MatlabとC ++ではそれぞれが異なります)ので、最終的な違いは非常に大きくなります)(違いがどのように大きくなり始めるかを知りたい場合は、ここにあります完全な出力です[すぐにリンク]が、これは質問とは関係ありません)
まず、数値計算法が最後のビットまでのsinの精度に依存している場合は、MPFRなどの任意精度のライブラリを使用する必要があります。
IEEE754 2008標準では、関数を正しく丸める必要はありません(ただし、「推奨」しています)。一部のClibmは、正しく丸められた三角関数を提供します。CRlibmと同様に、glibc libmは(通常、ほとんどのLinuxディストリビューションで使用されます)提供すると思います。他のほとんどの最新のlibmsは、1 ulp以内の三角関数(つまり、真の値の両側にある2つの浮動小数点値の1つ)を提供します。これは、忠実に丸められたと呼ばれることが多く、計算がはるかに高速です。
印刷したこれらの値はいずれも、IEEE 64ビット浮動小数点値として実際に発生することはありません(丸められている場合でも)。最も近い3つ(完全な精度で印刷)は次のとおりです。
0.477158760259608 405451814405751065351068973541259765625
0.477158760259608 46096296563700889237225055694580078125
0.477158760259608 516474116868266719393432140350341796875
必要な値は次のとおりです。
0.477158760259608 433132061388630377105954125778369485736356219 .. ..
(これはMathematicaが与えるもののようです)。
0.477158760259608 430531153841011107415427334794384396325832953 .. ..
どちらの場合も、上記のリストの最初のものが最も近いです(ただし、1の場合はほとんどありません)。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加