e^x 没有 math.h

9 c math numerical-methods

我试图在不使用 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}\n
Run 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}\n
Run Code Online (Sandbox Code Playgroud)\n

我的输出:

\n
8\n0.0\n1.0\n-1.0\n2.0\n-2.0\n100.0\n-100.0\n0.189376476361643\n
Run Code Online (Sandbox Code Playgroud)\n

右输出:

\n
1\n2.71825396825397\n0.367857142857143\n7.38899470899471\n0.135379188712522\n2.68811714181613e+043\n-2.91375564689153e+025\n1.20849374134639\n
Run Code Online (Sandbox Code Playgroud)\n

你可以看到我对 e \xe2\x88\x92100的回答的回答是绝对不正确的。为什么我的代码会输出这个?我可以做些什么来改进这个算法?

\n

dbu*_*ush 5

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)