3

遭遇した問題にどう対処すればよいか分からず、苦労していました。複雑な数式の一部として、すぐに二重にオーバーフローする部分を計算する必要があります。つまり、結果は最大 1.59*10^(1331) (mathematica で計算) になります。もちろんこれはdoubleの範囲外です。次に、私のLinuxシステムでgcc 4.6.3は16バイトのlong doubleを使用することを考えていました。

1) 倍精度 (8 バイト) の範囲は 10^(308) までです。long double は実際の精度を向上させますが、値の可能な数値範囲は増加させません。システムとコンパイラに応じて、またはどちらかになる可能性があると聞いたのを覚えています。本当 ?long double で値を計算しようとすると、少なくとも NaN が返されます。

2.) その後、これらの結果を実際に計算する方法を探していたところ、GNU を見つけましたgmp。非常に大きな整数を表現できると聞いたので、これが役立つかもしれないと思いました。ただし、ドキュメントを読むと、

 mpz_t x;
 mpz_init(x);
 mpz_set_*(x,#);

値をgmp整数データ型に割り当てることはできますが、そのためには、double や (u/s)int などの組み込みデータ型で表すことができる値を割り当てることしかできません。本当に巨大な数字を割り当てる方法はmpz_set_str()、文字列から数字を割り当てるために使用していました。複雑な計算の結果である数値を割り当てるにはどうすればよいですか? 簡単に言えば、数式は次のようになります。

long double res1,res2=0.0;
int a,b;
a=780;
b=741;
float d,d1,o,s; // can be values in [0.01,100]

res1=(2*(pow(b,2)*pow(E,b*(o + s))*(pow(d1,2) + pow(E,a*s)*(-1 + pow(E,a*o)) + pow(d,2)*(-1 + pow(E,a*s))) + pow(a,2)*pow(E,a*(o + s))*(pow(E,b*s)*(pow(E,b*o) + (-1 + d)*(1 + d + b*o)) + (-d + d1)*(d + d1 + b*o + b*d*s)) - a*b*(pow(d1,2)*(pow(E,a*(o + s)) + pow(E,b*(o + s))) + pow(E,a*o + (a + b)*s)*(-2 + 2*pow(E,b*o) - b*o) + d1*pow(E,a*s)*(-pow(E,b*o) + pow(E,a*o)*(1 + b*o)) + pow(d,2)*pow(E,a*s)*(-pow(E,b*o) + pow(E,b*(o + s)) + pow(E,a*o)*(-1 + pow(E,b*s) - b*s)) +  d*(-(d1*pow(E,b*(o + s))) + (1 + d1)*pow(E,b*o + a*s) - pow(E,a*s + b*(o + s)) + pow(E,b*s + a*(o + s))*(1 + b*o) + pow(E,a*(o + s))*(-1 - b*o + b*d1*s)))))......;

res2 もこの種のものであり、最終的に res1/res2 を計算する必要がありますが、これは通常非常に小さい数値になります。

数式を分割して mpg_z に項を追加し、項ごとに 2 倍の範囲を超えないようにすることを考えていましたが、数式が非常に長く複雑であるため、これはほとんど不可能です。

要約すると、問題は、中間結果が非常に大きくなり、それらを格納できるデータ型がないため、それを mpz に割り当ててこの問題を取り除くことができないことです。

double 値を計算し、実際に整数に mpz_t を使用したいことを認識しています。mpf_t は float 型しか扱えないので、私が理解している限り、これがそのような大きなデータを格納する唯一の方法です。正直なところ、 での表現については、まだ私の側で混乱が生じていgmpます。

これにアプローチする方法はありますか?

4

1 に答える 1

2

質問 1 long double を使用すると、double よりも大きな数を処理できます (指数と仮数精度の両方で)。ただし、目標が大きな整数を格納することである場合、1e308 の大きさは何の意味もないと考える必要があります。52/53 ビット (double) または 64 ビット (x86 拡張精度) の仮数精度のサイズだけを気にする必要があります。より大きな整数でそれを使用しようとすると、正しい大きさの順序が得られますが、正確な値は失われます (整数で計算する場合、一般に、概数で遊ぶ場合よりも、このことを気にかけます)。

質問 2 GMP の使用は良い選択です。他のライブラリも存在します。小さい値の場合、固定精度が拡張され、非常に高速なlibqdをよく使用しますが、これはあなた自身の問題には十分ではありません。今、あなたの質問は値の設定に関するものです:

  • 数値の文字列バージョンを使用することは、一般的には悪い考えです (これは、入出力目的でのみ保持する必要があります)。これは、基底変換と桁ごとの処理を含む低速の操作です。
  • GMP 型でできる限り多くのことを行うことが道です (速度を本当に気にし、ネイティブ型で計算される値の予想される範囲を完全に制御している場合を除きます)。
  • 数式が長すぎる場合は、あまり役に立ちません。しかし、GMP を使用することはそれほど難しいことではありません。実際に数式を変換できませんか? 数式にループに埋め込むことができるロジックはありますか? GMP を使用して式を C コードに変換するための、簡単で汚い python スクリプトを作成できますか?

mpz_tではなく.を使用する理由がよくわかりませんmpf_t。この型は、任意の長い浮動小数点数を実装します。で精度を設定できることに気づきましたmpf_set_default_precか?

于 2015-11-15T20:27:35.087 に答える