c++ - 正弦和余数的近似

标签 c++ c math

练习的目标是使用麦克劳林级数公式评估sin

#include <stdio.h>
#include <math.h>

double factorial(int n);

int main(void) {

    double x, p, r;
    int i, n;

    printf("Enter a positive double number and a non - negative integer : \n");
    scanf("%lf%d", &x, &n);

    if (x <= 0) {
        printf("Error: first argument must be a positive double.\n");
        return -1;
    }

    if (n < 0) {
        printf("Error: second argument must be a non - negative integer.\n");
        return -1;
    }

    p = 0;
    for (i = 0; i <= n; i++)
    {
        p += pow(-1, i) / factorial(2 * i + 1) * pow(x, 2 * i + 1);
    }

    r = fabs(sin(x) - p);

    printf("The %d-th order Maclaurin polynomial function at x=%f is %f, with an error approximation of %f.\n", n, x, p, r);



    getch();
    return 0;
}

double factorial(int n)
{
    int i;
    long result = 1;
    for (i = 1; i <= n; i++)
        result *= i;

    return result;
}

输入“12 16”时我得到奇怪的结果。为什么?

最佳答案

这里存在三个问题。

  • 正如 Mukit Chowdhury 回答的那样,多头不能容纳大阶乘。不过,正如GregS所说,16!应该没有问题。当您使用 long 来保存 21 时,您应该会遇到奇怪的结果!或更大,但您无需更改此输入的阶乘函数。不过,您可能应该使用类似以下内容的内容:

    double factorial(int n)
    {
        int i;
        double result = 1;
        for (i = 1; i <= n; i++)
            result *= i;
        return result;
    }
    
  • 在输入“12 16”上,您的代码声称正在计算 16 阶麦克劳林多项式,但实际上计算的是 33 阶麦克劳林多项式。 16 阶多项式的项高达 -x^15/15! + 0x^16。解决此问题的一种方法是更正 for 循环,如下所示:

    for (i = 1; i <= n; i+=2)
    {
        p += pow(-1, (i-1)/2) / factorial(i) * pow(x, i);
    }
    

    因此,您的代码在阶乘方面遇到了问题,但这只是因为您正在计算额外的项。如果您计算的项最多为 -x^15/15!,您应该能够正确计算多项式的值。

  • 16 阶麦克劳林多项式在 12 处的实际值为 -4306.756...这可能不是您所期望的,这可能是练习要点的一部分。为了获得准确的近似值,您应该期望最后一项很小,因此您需要 n!超过x^n。根据斯特林近似,n! ~ (n/e)^n,所以你想要 n > e*x,其中 e = 2.71828...,所以 n>=33。此时,误差为 0.005,将 n 增加 c 会使误差大小减小约 e^c 倍。
  • 当您减去大量数字以产生较小的最终结果时, double 算术中应该会出现较大的错误。这在这里可能不是问题,因为最大项的量级仅为 2^14 左右。您仍然可以获得足够的精度,以至于您不会注意到通过添加更多项无法非常接近 sin(12)。

关于c++ - 正弦和余数的近似,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29445615/

相关文章:

c++ - 为什么他们有系统字符串和标准字符串

c++ - 通过代码在 Windows 操作系统上启用和禁用 DST

javascript - 根据高度计算纵横比宽度

algorithm - 有谁知道如何进行 "inverse"三线性插值?

javascript - 节点 - 多个日期范围重叠

c++ - 使用 CMake 的实验性模块依赖扫描构建 C++ 模块

c++ - 使用c++将Mat转换为opencv中的内存

c - 在二叉树中看似无处设置根节点

c++ - 保护多线程访问的类实例

c - 如何使main方法中的变量可以在C中的其他方法中访问