我试图在不使用 math.h 的情况下找到 e x 。当x大于或小于 ~\xc2\xb120时,我的代码给出错误的答案。我尝试将所有双精度类型更改为长双精度类型,但它在输入上产生了一些垃圾。
\n我的代码是:
\n#include <stdio.h>\n\ndouble fabs1(double x) {\n if(x >= 0){\n return x;\n } else {\n return x*(-1);\n }\n}\n\ndouble powerex(double x) {\n double a = 1.0, e = a;\n for (int n = 1; fabs1(a) > 0.001; ++n) {\n a = a * x / n;\n e += a;\n }\n return e;\n}\n\nint main(){\n freopen("input.txt", "r", stdin);\n freopen("output.txt", "w", stdout);\n int n;\n scanf("%d", &n);\n for(int i = 0; i<n; i++) {\n double number;\n scanf("%lf", &number);\n double e = powerex(number);\n printf("%0.15g\\n", e);\n }\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n输入:
\n#include <stdio.h>\n\ndouble fabs1(double x) {\n if(x >= 0){\n return x;\n } else {\n return x*(-1);\n }\n}\n\ndouble powerex(double x) {\n double a = 1.0, e = a;\n for (int n = 1; fabs1(a) > 0.001; ++n) {\n a = a * x / n;\n e += a;\n }\n return e;\n}\n\nint main(){\n freopen("input.txt", "r", stdin);\n freopen("output.txt", "w", stdout);\n int n;\n scanf("%d", &n);\n for(int i = 0; i<n; i++) {\n double number;\n scanf("%lf", &number);\n double e = powerex(number);\n printf("%0.15g\\n", e);\n }\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n我的输出:
\n8\n0.0\n1.0\n-1.0\n2.0\n-2.0\n100.0\n-100.0\n0.189376476361643\nRun Code Online (Sandbox Code Playgroud)\n右输出:
\n1\n2.71825396825397\n0.367857142857143\n7.38899470899471\n0.135379188712522\n2.68811714181613e+043\n-2.91375564689153e+025\n1.20849374134639\nRun Code Online (Sandbox Code Playgroud)\n你可以看到我对 e \xe2\x88\x92100的回答的回答是绝对不正确的。为什么我的代码会输出这个?我可以做些什么来改进这个算法?
\n当x为负数时,每一项的符号交替。这意味着当使用正功率时,每个连续的总和的值会广泛变化,而不是逐渐增加。这意味着连续项的精度损失对结果有很大影响。
x要处理这个问题,请检查开头的符号。如果为负,则交换 的符号x来执行计算,然后当到达循环末尾时反转结果。
此外,您可以使用以下违反直觉的条件来减少迭代次数:
e != e + a
Run Code Online (Sandbox Code Playgroud)
从表面上看,这似乎应该永远是正确的。a但是,当 的值超出 的值的精度时,条件变为 false 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;
}
return invert ? 1/e : e;
}
Run Code Online (Sandbox Code Playgroud)
我们可以进一步优化,通过e使用 0 而不是进行初始化a,并在循环底部而不是顶部计算下一项,从而删除一次循环迭代:
double powerex(double x) {
double a = 1.0, e = 0;
int invert = x<0;
x = fabs1(x);
for (int n = 1; e != e + a ; ++n) {
e += a;
a = a * x / n;
}
return invert ? 1/e : e;
}
Run Code Online (Sandbox Code Playgroud)