为什么C中的sin计算代码返回错误的值?

为什么C中的sin计算代码返回错误的值?,c,equation-solving,C,Equation Solving,我想使用我自己的函数,根据以下等式计算用户输入的正弦: sin(x)=和(i=0)^n(-1)^i*(x^(2i+1)/(2i+1)!) 我有这个代码,据我所知,我做的和等式中写的完全一样: #包括 #包括 智力因素(智力因素) { int结果=1; 如果(系数>0) { 对于(int i=1;i 0) { 对于(int i=1;i这里的问题不一定是你的代码。这只是你对方程的期望。我在Wolfram Alpha中测试了泰勒级数的n=5,并使用查询从级数中减去sin(x) (sum (-1)^i

我想使用我自己的函数,根据以下等式计算用户输入的正弦:

sin(x)=和(i=0)^n(-1)^i*(x^(2i+1)/(2i+1)!)

我有这个代码,据我所知,我做的和等式中写的完全一样:

#包括
#包括
智力因素(智力因素)
{
int结果=1;
如果(系数>0)
{
对于(int i=1;i 0)
{

对于(int i=1;i这里的问题不一定是你的代码。这只是你对方程的期望。我在Wolfram Alpha中测试了泰勒级数的n=5,并使用查询从级数中减去sin(x)

(sum (-1)^i * x^(2i+1)/(2i+1)!, i=0 to 5) - sin(x)  
查看错误

正如你所看到的,当x在0左右时,级数的逼近效果非常好,但是当x超过3时,误差开始很大,并且增长非常快。当x=8时,误差的大小为67,这显然是无用的。为了得到合理的逼近,你需要使用n=15左右。只有5是非常小的

这里你要做的是利用sin(x)=sin(x+k*2*PI)这一事实,其中k是一个任意整数。如果x是负数,你可以简单地使用sin(x)=-sin(-x)这一事实。我展示了一个简单的例子来说明这一点:

double my_sin(double x, int n)
{
    double my_sin = 0;
    double sign = 1.0;

    // sin(-x) = -sin(x)
    // This does not improve accuracy. It's just to make the rest simpler
    if(x<0) {
        x=-x;
        sign *= -1;
    }

    // sin(x) = sin(k*2*PI + x)
    x -= 2*PI*floor(x/(2*PI));

    // Continue as usual

    return sign * my_sin;
}
但是,您的代码中有一个bug。请记住,应该包括j=n的情况,所以请更改

for (int j = 0; j < n ; j++)
瞄准某一精度 假设您需要3个正确的十进制数字。然后我们可以利用分子增长速度慢于分母的事实,执行如下操作:

    size_t denominator = 1;
    double numerator = x;
    double term;
    int s = -1;
    int j = 0;
    double tolerance = 0.001;

    do {
        denominator *= 2*j + 1;
        j++;
        s *= -1;

        term = numerator / denominator;

        ret += s * term;

        numerator *= x*x;
    } while(abs(term) > tolerance);

您的代码中存在许多问题:

  • factorial
    函数使用范围有限的整数算术进行计算。对于32位
    int
    long
    n>13
    函数,它将溢出未定义的行为
  • my_pow()
    函数不正确:它不适用于负值,因此为
    my_pow(-1,…)
    提供不正确的结果
您还应该首先将
x
减少到0和PI/2之间的数字,并增量计算序列的项

以下是一个带有测试套件的修改版本:

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

long int factorial(int factor) {
    long int result = 1;

    if (factor > 0) {
        for (int i = 1; i <= factor; i++) {
            result = result * i;
        }
    } else {
        result = 1;
    }
    return result;
}

double my_pow(double a, double b) {
    if (b == 0) {
        return 1;
    }

    double result = a;
    double increment = a;
    double i, j;

    for (i = 1; i < b; i++) {
        for (j = 1; j < a; j++) {
            result += increment;
        }
        increment = result;
    }
    return result;
}

double my_sin(double x, int n) {
    double my_sin = 0;
    for (int j = 0; j < n; j++) {
        double i = (double)j;
        double faculty_j = (double)factorial(2 * i + 1);
        my_sin = my_sin + (my_pow((-1.0), i) * (my_pow(x, 2.0 * i + 1.0) / faculty_j));
    }
    return my_sin;
}

double my_sin2(double x, int n) {
    double my_sin, term, sign = 1.0;
    if (x < 0) {
        x = -x;
        sign = -sign;
    }
    if (x >= 2 * M_PI) {
        x = fmod(x, 2 * M_PI);
    }
    if (x > M_PI) {
        x -= M_PI;
        sign = -sign;
    }
    if (x > M_PI / 2) {
        x = M_PI - x;
    }
    my_sin = term = x * sign;
    for (int i = 1; i <= n; i++) {
        term = -term * x * x / ((2 * i) * (2 * i + 1));
        my_sin += term;
    }
    return my_sin;
}

int main() {
    int i, n = 16, steps = 100;
    double x1 = -7.0, x2 = 7.0;
#if 0
    printf("n=");
    scanf("%i", &n);
    printf("x1=");
    scanf("%lf", &x1);
    printf("x2=");
    scanf("%lf", &x2);
    printf("steps=");
    scanf("%i", &steps);
#endif
    char buf1[20];
    char buf2[20];
    snprintf(buf1, sizeof(buf1), "my_sin(x,%d)", n);
    snprintf(buf2, sizeof(buf2), "my_sin2(x,%d)", n);
    printf("%17s  %17s  %17s  %17s  %17s  %17s\n",
           "x", "sin(x)", buf1, "error1", buf2, "error2");
    for (i = 0; i <= steps; i++) {
        double x = x1 + (x2 - x1) * ((double)i / steps);
        double s = sin(x);
        double s1 = my_sin(x, n);
        double s2 = my_sin2(x, n);
        printf("%17.14f  %17.14f  %17.14f  %17.14f  %17.14f  %17.14f\n",
               x, s, s1, s1 - s, s2, s2 - s);
    }
    return 0;
}
#包括
#包括
长整数阶乘(整数因子){
长整数结果=1;
如果(系数>0){
对于(int i=1;i=2*M_PI){
x=fmod(x,2*M_-PI);
}
如果(x>M_-PI){
x-=M_PI;
符号=-符号;
}
如果(x>M_PI/2){
x=M_PI-x;
}
my_sin=term=x*符号;

对于(inti=1;i
intmy\u sin
),真的吗?您已经声明了一个函数
intmy\u sin(双x,intn)
返回一个
双精度的
。这将永远无法正常工作。预期结果是什么?为了帮助调试,将复杂表达式拆分为更简单的表达式,将中间结果存储在临时变量中。这将更容易看到计算何时何地开始出错。另外,请阅读@AdrianMole当然可以,因为转换,泰勒级数在x接近零时收敛得更快。它将收敛于任意x,但需要更大的n。
double my_sin(double x, int n)
{
    double ret = 0;
    double sign = 1.0;

    if(x<0) {
        x=-x;
        sign *= -1;
    }

    x -= 2*PI*floor(x/(2*PI));

    if(x>PI) {
        x-=PI;
        sign *= -1;
    }

    if(x>PI/2) 
        x = PI - x;

    size_t denominator = 1;
    double numerator = x;
    int s = -1;

    for (int j = 0; j <= n ; j++) {
        denominator *= 2*j + 1;
        s *= -1;

        ret += s * numerator / denominator;

        numerator *= x*x;
    }

    return sign*ret;
}
    size_t denominator = 1;
    double numerator = x;
    double term;
    int s = -1;
    int j = 0;
    double tolerance = 0.001;

    do {
        denominator *= 2*j + 1;
        j++;
        s *= -1;

        term = numerator / denominator;

        ret += s * term;

        numerator *= x*x;
    } while(abs(term) > tolerance);
#include <math.h>
#include <stdio.h>

long int factorial(int factor) {
    long int result = 1;

    if (factor > 0) {
        for (int i = 1; i <= factor; i++) {
            result = result * i;
        }
    } else {
        result = 1;
    }
    return result;
}

double my_pow(double a, double b) {
    if (b == 0) {
        return 1;
    }

    double result = a;
    double increment = a;
    double i, j;

    for (i = 1; i < b; i++) {
        for (j = 1; j < a; j++) {
            result += increment;
        }
        increment = result;
    }
    return result;
}

double my_sin(double x, int n) {
    double my_sin = 0;
    for (int j = 0; j < n; j++) {
        double i = (double)j;
        double faculty_j = (double)factorial(2 * i + 1);
        my_sin = my_sin + (my_pow((-1.0), i) * (my_pow(x, 2.0 * i + 1.0) / faculty_j));
    }
    return my_sin;
}

double my_sin2(double x, int n) {
    double my_sin, term, sign = 1.0;
    if (x < 0) {
        x = -x;
        sign = -sign;
    }
    if (x >= 2 * M_PI) {
        x = fmod(x, 2 * M_PI);
    }
    if (x > M_PI) {
        x -= M_PI;
        sign = -sign;
    }
    if (x > M_PI / 2) {
        x = M_PI - x;
    }
    my_sin = term = x * sign;
    for (int i = 1; i <= n; i++) {
        term = -term * x * x / ((2 * i) * (2 * i + 1));
        my_sin += term;
    }
    return my_sin;
}

int main() {
    int i, n = 16, steps = 100;
    double x1 = -7.0, x2 = 7.0;
#if 0
    printf("n=");
    scanf("%i", &n);
    printf("x1=");
    scanf("%lf", &x1);
    printf("x2=");
    scanf("%lf", &x2);
    printf("steps=");
    scanf("%i", &steps);
#endif
    char buf1[20];
    char buf2[20];
    snprintf(buf1, sizeof(buf1), "my_sin(x,%d)", n);
    snprintf(buf2, sizeof(buf2), "my_sin2(x,%d)", n);
    printf("%17s  %17s  %17s  %17s  %17s  %17s\n",
           "x", "sin(x)", buf1, "error1", buf2, "error2");
    for (i = 0; i <= steps; i++) {
        double x = x1 + (x2 - x1) * ((double)i / steps);
        double s = sin(x);
        double s1 = my_sin(x, n);
        double s2 = my_sin2(x, n);
        printf("%17.14f  %17.14f  %17.14f  %17.14f  %17.14f  %17.14f\n",
               x, s, s1, s1 - s, s2, s2 - s);
    }
    return 0;
}
x sin(x) my_sin(x,16) error1 my_sin2(x,16) error2 -7.00000000000000 -0.65698659871879 -5.77359164449339 -5.11660504577460 -0.65698659871879 -0.00000000000000 -6.86000000000000 -0.54535677064030 -5.65811981160352 -5.11276304096322 -0.54535677064030 0.00000000000000 -6.72000000000000 -0.42305539714300 -5.54264797871365 -5.11959258157066 -0.42305539714300 -0.00000000000000 -6.58000000000000 -0.29247567242987 -5.42717614582379 -5.13470047339392 -0.29247567242987 -0.00000000000000 -6.44000000000000 -0.15617278154321 -5.31170431293392 -5.15553153139071 -0.15617278154321 -0.00000000000000 -6.30000000000000 -0.01681390048435 -5.19623248004405 -5.17941857955970 -0.01681390048435 -0.00000000000000 -6.16000000000000 0.12287399510655 -5.08076064715418 -5.20363464226073 0.12287399510655 -0.00000000000000 -6.02000000000000 0.26015749143047 -4.96528881426431 -5.22544630569478 0.26015749143047 -0.00000000000000 -5.88000000000000 0.39235022399145 -4.84981698137445 -5.24216720536590 0.39235022399145 -0.00000000000000 -5.74000000000000 0.51686544439743 -4.73434514848458 -5.25121059288201 0.51686544439743 -0.00000000000000 -5.60000000000000 0.63126663787232 -4.61887331559471 -5.25013995346703 0.63126663787232 -0.00000000000000 -5.46000000000000 0.73331520099566 -4.50340148270484 -5.23671668370050 0.73331520099566 -0.00000000000000 -5.32000000000000 0.82101424671125 -4.38792964981498 -5.20894389652622 0.82101424671125 -0.00000000000000 -5.18000000000000 0.89264767942823 -4.27245781692511 -5.16510549635334 0.89264767942823 0.00000000000000 -5.04000000000000 0.94681377559261 -4.15698598403524 -5.10379975962785 0.94681377559261 -0.00000000000000 -4.90000000000000 0.98245261262433 -4.04151415114537 -5.02396676376970 0.98245261262433 -0.00000000000000 -4.76000000000000 0.99886680949041 -3.92604231825550 -4.92490912774592 0.99886680949041 0.00000000000000 -4.62000000000000 0.99573517306225 -3.81057048536564 -4.80630565842788 0.99573517306225 0.00000000000000 -4.48000000000000 0.97311898322517 -3.69509865247577 -4.66821763570094 0.97311898322517 0.00000000000000 -4.34000000000000 0.93146079375324 -3.57962681958590 -4.51108761333914 0.93146079375324 0.00000000000000 -4.20000000000000 0.87157577241359 -3.46415498669603 -4.33573075910962 0.87157577241359 0.00000000000000 -4.06000000000000 0.79463574975740 -3.34868315380617 -4.14331890356356 0.79463574975740 0.00000000000000 -3.92000000000000 0.70214628873081 -3.23321132091630 -3.93535760964710 0.70214628873081 0.00000000000000 -3.78000000000000 0.59591722380776 -3.11773948802643 -3.71365671183419 0.59591722380776 -0.00000000000000 -3.64000000000000 0.47802724613534 -3.00226765513656 -3.48029490127191 0.47802724613534 0.00000000000000 -3.50000000000000 0.35078322768962 -2.88679582224669 -3.23757904993631 0.35078322768962 0.00000000000000 -3.36000000000000 0.21667508038738 -2.77132398935683 -2.98799906974421 0.21667508038738 0.00000000000000 -3.22000000000000 0.07832703347086 -2.65585215646696 -2.73417918993782 0.07832703347086 0.00000000000000 -3.08000000000000 -0.06155371742991 -2.54038032357709 -2.47882660614718 -0.06155371742991 0.00000000000000 -2.94000000000000 -0.20022998472177 -2.42490849068722 -2.22467850596545 -0.20022998472177 0.00000000000000 -2.80000000000000 -0.33498815015591 -2.30943665779736 -1.97444850764145 -0.33498815015590 0.00000000000000 -2.66000000000000 -0.46319126493035 -2.19396482490749 -1.73077355997714 -0.46319126493035 0.00000000000000 -2.52000000000000 -0.58233064952408 -2.07849299201762 -1.49616234249354 -0.58233064952408 0.00000000000000 -2.38000000000000 -0.69007498355694 -1.96302115912775 -1.27294617557082 -0.69007498355694 0.00000000000000 -2.24000000000000 -0.78431592508442 -1.84754932623788 -1.06323340115346 -0.78431592508442 0.00000000000000 -2.10000000000000 -0.86320936664887 -1.73207749334802 -0.86886812669914 -0.86320936664887 0.00000000000000 -1.96000000000000 -0.92521152078817 -1.61660566045815 -0.69139413966998 -0.92521152078817 0.00000000000000 -1.82000000000000 -0.96910912888046 -1.50113382756828 -0.53202469868783 -0.96910912888046 0.00000000000000 -1.68000000000000 -0.99404320219808 -1.38566199467841 -0.39161879248034 -0.99404320219808 -0.00000000000000 -1.54000000000000 -0.99952583060548 -1.27019016178855 -0.27066433118307 -0.99952583060548 0.00000000000000 -1.40000000000000 -0.98544972998846 -1.15471832889868 -0.16926859891022 -0.98544972998846 0.00000000000000 -1.26000000000000 -0.95209034159052 -1.03924649600881 -0.08715615441829 -0.95209034159052 -0.00000000000000 -1.12000000000000 -0.90010044217651 -0.92377466311894 -0.02367422094244 -0.90010044217651 0.00000000000000 -0.98000000000000 -0.83049737049197 -0.80830283022907 0.02219454026290 -0.83049737049197 -0.00000000000000 -0.84000000000000 -0.74464311997086 -0.69283099733921 0.05181212263165 -0.74464311997086 0.00000000000000 -0.70000000000000 -0.64421768723769 -0.57735916444934 0.06685852278835 -0.64421768723769 0.00000000000000 -0.56000000000000 -0.53118619792088 -0.46188733155947 0.06929886636141 -0.53118619792088 0.00000000000000 -0.42000000000000 -0.40776045305957 -0.34641549866960 0.06134495438997 -0.40776045305957 -0.00000000000000 -0.28000000000000 -0.27635564856411 -0.23094366577974 0.04541198278438 -0.27635564856411 0.00000000000000 -0.14000000000000 -0.13954311464424 -0.11547183288987 0.02407128175437 -0.13954311464424 0.00000000000000 0.00000000000000 0.00000000000000 0.00000000000000 0.00000000000000 0.00000000000000 0.00000000000000 0.14000000000000 0.13954311464424 0.11547183288987 -0.02407128175437 0.13954311464424 0.00000000000000 0.28000000000000 0.27635564856411 0.23094366577974 -0.04541198278438 0.27635564856411 0.00000000000000 0.42000000000000 0.40776045305957 0.34641549866960 -0.06134495438997 0.40776045305957 0.00000000000000 0.56000000000000 0.53118619792088 0.46188733155947 -0.06929886636141 0.53118619792088 0.00000000000000 0.70000000000000 0.64421768723769 0.57735916444934 -0.06685852278835 0.64421768723769 0.00000000000000 0.84000000000000 0.74464311997086 0.69283099733921 -0.05181212263165 0.74464311997086 0.00000000000000 0.98000000000000 0.83049737049197 0.80830283022907 -0.02219454026290 0.83049737049197 0.00000000000000 1.12000000000000 0.90010044217650 0.20895817141848 -0.69114227075803 0.90010044217650 0.00000000000000 1.26000000000000 0.95209034159052 0.23507794284579 -0.71701239874473 0.95209034159052 0.00000000000000 1.40000000000000 0.98544972998846 0.26119771427310 -0.72425201571536 0.98544972998846 0.00000000000000 1.54000000000000 0.99952583060548 0.28731748570041 -0.71220834490507 0.99952583060548 0.00000000000000 1.68000000000000 0.99404320219808 0.31343725712772 -0.68060594507036 0.99404320219808 0.00000000000000 1.82000000000000 0.96910912888046 0.33955702855503 -0.62955210032543 0.96910912888046 -0.00000000000000 1.96000000000000 0.92521152078817 0.36567679998234 -0.55953472080583 0.92521152078817 0.00000000000000 2.10000000000000 0.86320936664887 -2.81259124559189 -3.67580061224076 0.86320936664887 0.00000000000000 2.24000000000000 0.78431592508442 -3.00009732863135 -3.78441325371577 0.78431592508442 -0.00000000000000 2.38000000000000 0.69007498355694 -3.18760341167081 -3.87767839522775 0.69007498355694 -0.00000000000000 2.52000000000000 0.58233064952408 -3.37510949471027 -3.95744014423435 0.58233064952408 -0.00000000000000 2.66000000000000 0.46319126493035 -3.56261557774973 -4.02580684268007 0.46319126493035 0.00000000000000 2.80000000000000 0.33498815015591 -3.75012166078919 -4.08510981094509 0.33498815015591 -0.00000000000000 2.94000000000000 0.20022998472177 -3.93762774382865 -4.13785772855042 0.20022998472177 -0.00000000000000 3.08000000000000 0.06155371742991 -15.52969329095525 -15.59124700838516 0.06155371742991 -0.00000000000000 3.22000000000000 -0.07832703347086 -16.23558844054412 -16.15726140707325 -0.07832703347086 -0.00000000000000 3.36000000000000 -0.21667508038738 -16.94148359013299 -16.72480850974561 -0.21667508038738 -0.00000000000000 3.50000000000000 -0.35078322768962 -17.64737873972186 -17.29659551203224 -0.35078322768962 -0.00000000000000 3.64000000000000 -0.47802724613534 -18.35327388931075 -17.87524664317541 -0.47802724613534 -0.00000000000000 3.78000000000000 -0.59591722380777 -19.05916903889963 -18.46325181509186 -0.59591722380776 0.00000000000000 3.92000000000000 -0.70214628873081 -19.76506418848850 -19.06291789975770 -0.70214628873081 -0.00000000000000 4.06000000000000 -0.79463574975740 -785.98288527038937 -785.18824952063198 -0.79463574975740 -0.00000000000000 4.20000000000000 -0.87157577241359 -813.08574338316134 -812.21416761074772 -0.87157577241359 0.00000000000000 4.34000000000000 -0.93146079375324 -840.18860149593320 -839.25714070217998 -0.93146079375324 0.00000000000000 4.48000000000000 -0.97311898322517 -867.29145960870540 -866.31834062548023 -0.97311898322517 0.00000000000000 4.62000000000000 -0.99573517306225 -894.39431772147736 -893.39858254841511 -0.99573517306225 -0.00000000000000 4.76000000000000 -0.99886680949041 -921.49717583424911 -920.49830902475867 -0.99886680949041 -0.00000000000000 4.90000000000000 -0.98245261262433 -948.60003394702130 -947.61758133439696 -0.98245261262433 0.00000000000000 5.04000000000000 -0.94681377559261 -218497.22569403689704 -218496.27888026129222 -0.94681377559261 0.00000000000000 5.18000000000000 -0.89264767942823 -224566.59307442686986 -224565.70042674744036 -0.89264767942823 0.00000000000000 5.32000000000000 -0.82101424671125 -230635.96045481678448 -230635.13944057008484 -0.82101424671125 0.00000000000000 5.46000000000000 -0.73331520099566 -236705.32783520672820 -236704.59452000574674 -0.73331520099566 0.00000000000000 5.60000000000000 -0.63126663787232 -242774.69521559661371 -242774.06394895873382 -0.63126663787232 0.00000000000000 5.74000000000000 -0.51686544439743 -248844.06259598652832 -248843.54573054212960 -0.51686544439743 0.00000000000000 5.88000000000000 -0.39235022399145 -254913.42997637641383 -254913.03762615242158 -0.39235022399145 0.00000000000000 6.02000000000000 -0.26015749143047 -26739506.86298683285713 -26739506.60282934084535 -0.26015749143047 0.00000000000000 6.16000000000000 -0.12287399510655 -27361355.85980049148202 -27361355.73692649602890 -0.12287399510655 0.00000000000000 6.30000000000000 0.01681390048435 -27983204.85661410912871 -27983204.87342800945044 0.01681390048435 0.00000000000000 6.44000000000000 0.15617278154321 -28605053.85342779010534 -28605054.00960057228804 0.15617278154321 0.00000000000000 6.58000000000000 0.29247567242987 -29226902.85024143010378 -29226903.14271710067987 0.29247567242987 0.00000000000000 6.72000000000000 0.42305539714300 -29848751.84705507382751 -29848752.27011046931148 0.42305539714300 0.00000000000000 6.86000000000000 0.54535677064030 -30470600.84386872500181 -30470601.38922549411654 0.54535677064030 0.00000000000000 7.00000000000000 0.65698659871879 -31092449.84068236500025 -31092450.49766896292567 0.65698659871879 0.00000000000000