我試圖在不使用 math.h 的情況下找到 e x。當x大于或小于 ~±20時,我的代碼給出了錯誤的答案。我試圖將所有 double 型別更改為 long double 型別,但它在輸入中產生了一些垃圾。
我的代碼是:
#include <stdio.h>
double fabs1(double x) {
if(x >= 0){
return x;
} else {
return x*(-1);
}
}
double powerex(double x) {
double a = 1.0, e = a;
for (int n = 1; fabs1(a) > 0.001; n) {
a = a * x / n;
e = a;
}
return e;
}
int main(){
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
int n;
scanf("%d", &n);
for(int i = 0; i<n; i ) {
double number;
scanf("%lf", &number);
double e = powerex(number);
printf("%0.15g\n", e);
}
return 0;
}
輸入:
8
0.0
1.0
-1.0
2.0
-2.0
100.0
-100.0
0.189376476361643
我的輸出:
1
2.71825396825397
0.367857142857143
7.38899470899471
0.135379188712522
2.68811714181613e 043
-2.91375564689153e 025
1.20849374134639
右輸出:
1
2.71828182845905
0.367879441171442
7.38905609893065
0.135335283236613
2.68811714181614e 43
3.72007597602084e-44
1.20849583696666
你可以看到我對 e -100 的回答是完全錯誤的。為什么我的代碼輸出這個?我能做些什么來改進這個演算法?
uj5u.com熱心網友回復:
當x為負時,每一項的符號交替出現。這意味著當使用正冪時,每個連續的總和在值上廣泛切換,而不是逐漸增加。這意味著連續項的精度損失對結果有很大影響。
要處理此問題,請檢查開始時的符號x。如果為負,則切換符號x進行計算,然后當您到達回圈末尾時反轉結果。
此外,您可以使用以下違反直覺的條件來減少迭代次數:
e != e a
從表面上看,這似乎應該總是正確的。但是,當 的值a超出值的精度時,條件變為假e,在這種情況下,添加a到e不會改變 的值e。
double powerex(double x) {
double a = 1.0, e = a;
int invert = x<0;
x = fabs1(x);
for (int n = 1; e != e a ; n) {
a = a * x / n;
e = a;
printf("a=%.15f, e=%.15f\n", a, e);
}
return invert ? 1/e : e;
}
uj5u.com熱心網友回復:
對于大于 1 左右的 x 值,您可以考慮單獨處理整數部分并通過平方計算 e 的冪。(例如 e^9 = ((e2)2)2.e 乘以 4)
的確,泰勒發展的總稱,x^n/n!僅在 n>x 后才開始減少(每次乘以 x/k),因此求和至少需要 x 項。另一方面,e^n 最多可以在 2lg(n) 次乘法中高效計算,這樣效率更高,更準確。
所以我會建議
- 取 x 的小數部分并使用泰勒,
- 當整數部分為正時,乘以 e 的那個冪,
- 當整數部分為零時,你就完成了,
- 當整數部分為負時,除以 e 的那個冪。
您甚至可以通過考慮四分之一來節省更多:在最壞的情況下 (x=1),泰勒需要 18 項才能使最后一項變得可以忽略不計。如果您考慮從 x 中減去 1/4 的直接劣倍數(并通過 e 的預先計算的冪來補償乘法),則項數將下降到 12。
例如 e^0.8 = e^(3/4 0.05) = 2.1170000166126747。e^0.05
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/383940.html
下一篇:bash腳本中的“預期運算元”
