我正在使用泰勒級數計算 e^x 并注意到當我們計算負 x 時絕對誤差很大。是因為我們沒有足夠的精度來計算它嗎?
(我知道為了防止它,我們可以使用 e^(-x)=1/e^x)
#include <stdio.h>
#include <math.h>
double Exp(double x);
int main(void)
{
double x;
printf("x=");
scanf("%le", &x);
printf("%le", Exp(x));
return 0;
}
double Exp(double x)
{
double h, eps = 1.e-16, Sum = 1.0;
int i = 2;
h = x;
do
{
Sum = h;
h *= x / i;
i ;
} while (fabs(h) > eps);
return Sum ;
}
例如:x=-40 值是 4.24835e-18 但程式給我 3.116952e-01。絕對誤差是 ~0.311
x=-50 值是 1.92875e-22 程式給我 2.041833e 03。絕對誤差是 ~2041.833
uj5u.com熱心網友回復:
該問題是由演算法中間階段的舍入錯誤引起的。在h迅速成長為40/2 * 40/3 * 40 / 4 * ...和符號振蕩。的值i,h和Sum用于x=-40連續迭代可以下方(為簡潔起見省略了一些資料點)中找到:
x=-40
i=2 h=800 Sum=-39
i=3 h=-10666.7 Sum=761
i=4 h=106667 Sum=-9905.67
i=5 h=-853333 Sum=96761
i=6 h=5.68889e 06 Sum=-756572
...
i=37 h=-1.37241e 16 Sum=6.63949e 15
i=38 h=1.44464e 16 Sum=-7.08457e 15
i=39 h=-1.48168e 16 Sum=7.36181e 15
i=40 h=1.48168e 16 Sum=-7.45499e 15
i=41 h=-1.44554e 16 Sum=7.36181e 15
i=42 h=1.37671e 16 Sum=-7.09361e 15
i=43 h=-1.28066e 16 Sum=6.67346e 15
i=44 h=1.16423e 16 Sum=-6.13311e 15
i=45 h=-1.03487e 16 Sum=5.50923e 15
i=46 h=8.99891e 15 Sum=-4.83952e 15
...
i=97 h=-2610.22 Sum=1852.36
i=98 h=1065.4 Sum=-757.861
i=99 h=-430.463 Sum=307.534
...
i=138 h=1.75514e-16 Sum=0.311695
i=139 h=-5.05076e-17 Sum=0.311695
3.116952e-01
sum 的峰值為7e15。這就是精度丟失的地方。型別double可以1e-16準確地表示。這給出了大約 的預期絕對誤差0.1 - 1。由于預期和(的值exp(-40)接近于零,最終絕對誤差接近于部分和的最大絕對誤差。
因為x=-50sum 的峰值是1.5e20給出絕對誤差的原因,這是由于double大約1e3 - 1e4接近觀察到的值的有限表示。
如果不對演算法進行重大更改以避免形成這些部分和,則無法修復太多內容。或者,計算exp(-x)為1/exp(x)。
uj5u.com熱心網友回復:
當“x”遠為負數時,e^x與 相比變得非常小eps=1.e-16。這意味著h可能小于eps第一次迭代后。
為了解決這個問題,您可以使用固定次數的迭代,或者使用相對于迄今為止的總和的 epsilon:
do {
....
} while (fabs(h/sum) > eps);
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/357613.html
上一篇:C中的陣列地址有問題嗎?
下一篇:使用鏈接的哈希表有問題
