0

C++ でいくつかの数学的アルゴリズムを実装するために、MS Visual C++ 2005 を使用しています。私の C++ コードは、Matlab で生成された小数点以下 12 桁の精度 (866.333333333333 など) の 10K double データ型の入力値を取ります。次に、私のコードはいくつかの計算を行い、同じアルゴリズムが同じ入力値で実行されたときに、matlab 出力と同じになるはずの機械的エンティティの損傷値である結果を返します。

私の問題は、matlab が小数点以下 12 桁の精度で 10k の入力値を与えることですが、私の C++ コードでは小数点以下 15 桁になります。つまり、matlab の 866.333333333333 は、C++ では 866.33333333333303 として使用されます。これが IEEE754 浮動小数点表現であることはわかっています。しかし、入力でのこの非常に小さな変更により、C++ 出力と matlab 出力を比較すると、最終結果に測定可能な違いが生じます。奇妙に聞こえるかもしれませんが、これが観察とは何かということです。ここでコードを共有できればと思いますが、非常に機密です。誰かがこれを乗り越えるために私を助けてくれれば、本当に感謝しています。

前もって感謝します...!

4

2 に答える 2

2

この質問 (およびすべての回答) が、小数点以下の桁数ではなく有効桁数で構成されていると、より正確になります。Itamar Katz が示唆したように、IEEE 標準では、倍精度浮動小数点数を仮数 (仮数と呼ぶもの) として 52 ビットで格納します。標準では余分なビットも意味するため、倍精度浮動小数点数には 53 の有効ビットがあります。2 進数を 10 進数に変換すると、15 桁または 16 桁の有効数字に変換されます。

Matlab も Visual C++ も (任意精度のライブラリや 128 ビットの fp 数値を使用するなどの追加機能がなければ) 有効桁数の標準サイズを超える double を格納できません。どちらの言語でも、プログラムが 15 桁 (または 16 桁) を超える 10 進数の数字を表示する場合、超過した桁を信頼することはできません。それらは数値の格納された表現から来たものではなく、メモリと画面の間のどこかに追加されたものです。おそらく、「役立つ」数値フォーマッタは、要求した 19 桁が表示されるまで右端の桁を単純に拡張しただけです。 (または何でも)。

C ++からMatlabへ/から数値を転送する方法、または数値を転送することさえ、質問から完全には明らかではありません。Matlab プログラムの結果を再現する C++ プログラムを書こうとしているだけかもしれません。(私たちはここで多くのことを行っているので、この分野での経験があります。)

「テキスト」ファイルを使用する場合は、数値ではなく数値の表現を転送しています。プログラムがテキスト '15.833' を double 変数に読み込む場合、仮数の余分な数字が取る値について仮定を行うのは安全ではありません。特に、それらが 0 に設定されると想定するべきではありません -- まあ、C++ に詳しい人なら、言語標準ではこれが保証されていると教えてくれるかもしれませんが、Matlab では保証されておらず、C++ はそうではないと思います。どちらかです。追加の数字を設定する場合は、テキスト表現で指定します。これでも、テキスト ファイルで指定された値を正確に保存することは保証されません。変数は、(おそらく) テキスト内の値に最も近い fp 番号を保持します。

ただし、テキスト ファイルが Matlab (または C++) によって記述され、数値のテキスト表現に 15 桁または 16 桁を書き込む場合、それは fp 数値全体のテキスト表現である必要があり、別のプログラムで読み取ったときに翻訳される必要があります。同じfp番号に。ただし、「すべき」と書いていることと、その数字は少なくとも 2 回翻訳されており、コンピューターの数字から目を離すと奇妙なことが起こることに注意してください。

C++ と Matlab の間でデータをビット単位で正確に転送するためのより良い選択は、バイナリ ファイル形式を使用することです。これは double の 64 ビットすべてを 64 ビットとして格納するものです。Matlab MAT ファイル形式は、標準で指定された形式で IEEE754 数値を確実に格納します。

前述のガフのすべてが、別の根本的な問題とは無関係である可能性があります。その問題は、アルゴリズムが安定していない可能性があります。これはまったく別のトピックです。

要約すると:

  1. プログラム間で数値をバイナリ表現で転送します (ファイルまたはメッセージ パッシングまたはその他のメカニズムを完全に使用するかどうかに関係なく)。
  2. 倍精度浮動小数点数の 10 進数表現で 15 を超える有効数字を信頼しないでください。

さらに、コードで特別な対策を講じない限り、プログラムは進行するにつれて徐々に精度を失い、下位桁がすべて疑わしい現実になります。あなたが示唆しているアプリケーションの場合、コードの背後にある科学が、有効数字の 15 桁目が異なる 2 つの出力が異なる値を表すという仮説をサポートしている可能性は低いです。入力の基準となる測定値の精度は?

于 2012-04-05T09:12:14.007 に答える
1
  1. 浮動小数点データ型は、小数点以下の桁数ではなく、数値を表すために使用されるビット数と、これらのビットを解釈するために使用される規則 (つまり、IEEE754 標準) によって定義されます。
  2. 一般に、2 つの異なる "環境" (つまり、プラットフォーム/CPU/コンパイラなど) で同じ出力 (同じ入力が与えられた場合) を達成することは簡単な作業ではありません。a+b+c大まかな例として、コンパイラがas(a+b)+cまたはのような式を計算する際に自由度がa+(b+c)あり、浮動小数点計算では異なる結果になる可能性があるという事実を考えてみましょう。再考することを強くお勧めします --- まったく同じ結果を得ることは本当に重要ですか?
  3. 2に書かれていることにもかかわらず、あなたの場合は可能かもしれません。最初のステップとして、テキストではなく、データのバイナリ表現を使用する必要があります。つまり、データを表すバイトを保持し、それを C++ コードに渡します。たとえば、 を渡す代わりに1.0、pass を渡します0x3FF0000000000000(ただし1.0、正確にバイナリで表現できます --- これは単なる例です)。

もちろん、いくつかのコードが役立ちます。機密情報を漏らさずに問題を示すおもちゃの例を作成してみてください。

于 2012-04-05T07:41:18.713 に答える