質問
この種の式を使用してe ^ xを計算することになっています。
e ^ x = 1 +(x ^ 1/1!)+(x ^ 2/2!)......
私はこれまでにこのコードを持っています:
while (result >= 1.0E-20 )
{
power = power * input;
factorial = factorial * counter;
result = power / factorial;
eValue += result;
counter++;
iterations++;
}
今の私の問題は、階乗がlong long型であるため、20を超える数値を実際に格納できないことです。そのため、プログラムはそのポイントに達すると面白い数字を出力します。.
正しいソリューションのX値は最大709であるため、e ^ 709の出力は8.21840746155e + 307です
プログラムはC ++で記述されています。
解決
x ^ nとnの両方! nで急速に大きくなり(それぞれ指数関数的および超指数関数的に)、使用するデータ型はすぐにオーバーフローします。一方、x ^ n / n! (最終的に)ダウンし、小さいときに停止できます。つまり、x ^(n + 1)/(n + 1)という事実を使用してください! =(x ^ n / n!)*(x /(n + 1))。このように言う:
term = 1.0;
for(n=1; term >= 1.0E-10; n++)
{
eValue += term;
term = term * x / n;
}
(このボックスにコードを直接入力しましたが、動作するはずです。)
編集:用語x ^ n / nに注意してください! xが大きい場合、しばらくの間増加し、その後減少します。 x = 709の場合、0に減少する前に〜1e + 306になります。これは、double
が処理できる範囲の限界です(term*x
の範囲は〜1e308で、long double
はそれを押し上げます)。しかし、term = term / n * x
は正常に機能します。もちろん、最終的な result e x はどの用語よりも大きいため、結果に対応するのに十分な大きさのデータ型を使用していると仮定すると、罰金。
(x = 709の場合、<=>を使用すれば<=>を使用しても問題ありませんが、710では機能しません。)
他のヒント
factorial
のタイプをlong long
からdouble
に変更するとどうなりますか?
別の解決策を考えることができます。
pow(e,x) = pow(10, m) * b
でb
が>=1
および< 10
である場合、
m = trunc( x * log10(e) )
ここでlog10(e)
は定数因子です。
and
b = pow(e,x)/pow(10, m ) = pow(e,x)/pow(e,m/log10(e)) = pow (e,x-m/log10(e))
これにより、以下が得られます。
z = x-m/log10(e)
0から3の間になり、SreevartsRで指定されたb = pow(e,z)
を使用します。
そして最終的な答えは
bは基数(有効数字)、mは仮数(大きさの順)です。
これは、SreevartsRアプローチよりも高速であり、高精度を使用する必要がない場合があります。
幸運を祈ります。
これは、xが0未満で負の値が大きい場合でも機能します。その場合、zは0から-3の間になり、他のアプローチよりも高速になります。
zは-3から3であり、最初の20桁の有効数字が必要な場合、pow(e、z)式は3 ^ 37/37以来37項までしか評価できません! =〜3.2e-26。
ここで紹介したのは、多項式を計算するための Hornerスキームのアプリケーションです。
>