遭遇した問題にどう対処すればよいか分からず、苦労していました。複雑な数式の一部として、すぐに二重にオーバーフローする部分を計算する必要があります。つまり、結果は最大 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
ます。
これにアプローチする方法はありますか?