创建自定义正弦函数

时间:2018-02-13 02:58:27

标签: c factorial sin taylor-series

我尝试使用sineTaylor Series创建一个自定义c函数,用于计算系列中包含10个术语的sin,但我得到了当我尝试找到sine(x) x > 6时的错误结果。

适用于-5 < x < 5,但超出该范围的任何内容都无法产生正确的结果。

我希望sin(10)返回接近-0.5440的内容,但获取1418.0269775391

我已将所有内容放在一个文件中,因此更容易。

#include <stdio.h>
#include <stdlib.h>

double factorial(double n);
double power(double n, double pow);
double sine(double n);

// This is supposed to all go in a .c file and reference the .h stuff above
// This is the actual implementation of the functions declared above
double factorial(double n) {
    // 0! = 1 so just return it
    if(n == 0) {
        return 1;
    }
    // Recursively call factorial with n-1 until n == 0
    return n * (factorial(n - 1)); 
}


double power(double n, double power) {
    double result = n;
    // Loop as many times as the power and just multiply itself power amount of times
    for(int i = 1; i < power; i++) {
        result = n * result;
    }
    return result;
}

double sine(double n) {
    double result = n;
    double coefficent = 3; // Increment this by 2 each loop
    for(int i = 0; i < 10; i++) { // Change 10 to go out to more/less terms
        double pow = power(n, coefficent);
        double frac = factorial(coefficent);
        printf("Loop %d:\n%2.3f ^ %2.3f = %2.3f\n", i, n, coefficent, pow);
        printf("%2.3f! = %2.3f\n", coefficent, frac);

        // Switch between adding/subtracting
        if(i % 2 == 0) { // If the index of the loop is divided by 2, the index is even, so subtract
            result = result - (pow/frac); // x - ((x^3)/(3!)) - ((x^5)/(5!))...
        } else {
            result = result + (pow/frac); // x - ((x^3)/(3!)) + ((x^5)/(5!))...
        }
        coefficent = coefficent + 2;
        printf("Result = %2.3f\n\n", result);
    }
    return result;
}

// main starting point. This is suppossed to #include "functions.c" which contain the above functions in it
int main(int argc, char** argv) {

    double number = atof(argv[1]); // argv[1] = "6"
    double sineResult = sine(number);
    printf("%1.10f", sineResult);
    return (0);
}

3 个答案:

答案 0 :(得分:2)

正如我在Python: Calculate sine/cosine with a precision of up to 1 million digits

中所说的那样
  

x 0 为中心的真实泰勒展开是:

     

     

其中 R n 拉格朗日剩余

     

     

请注意,只要 x 离开中心, R n 就会快速增长    X <子> 0

     

由于您正在实施 Maclaurin系列(泰勒系列   以0)为中心而不是一般的泰勒系列,你的功能   在尝试计算 sin(x)时会给出非常错误的结果    x 的重要值。

因此,在您for函数的sine()循环之前,您必须将域名减少到至少 [ - pi,pi] ...如果将其减少到 [0,pi] 并利用正弦的奇偶校验。

要修复您的代码,您需要math.h fmod(),所以您可以这样做:

#include <math.h>

// Your code

double sine (double n) {
    // Define PI
    const double my_pi = 3.14159265358979323846;
    // Sine's period is 2*PI
    n = fmod(n, 2 * my_pi);
    // Any negative angle can be brought back
    // to it's equivalent positive angle
    if (n < 0) {
        n = 2 * my_pi - n;
    }
    // Sine is an odd function...
    // let's take advantage of it.
    char sign = 1;
    if (n > my_pi) {
        n -= my_pi;
        sign = -1;
    }
    // Now n is in range [0, PI].

    // The rest of your function is fine

    return sign * result;
}

现在如果你真的讨厌math.h模块,你可以像这样实现自己的fmod()

double fmod(double a, double b)
{
    double frac = a / b;
    int floor = frac > 0 ? (int)frac : (int)(frac - 0.9999999999999999);
    return (a - b * floor);
}

Try it online!

答案 1 :(得分:0)

在我对问题的评论中列出的更正后,建议的代码如下:

dataFrame.write.parquet(s3Path)

,结果输出如下:

#include <stdio.h>
#include <stdlib.h>

double factorial(double n);
double power(double n, double pow);
double sine(double n);

// This is supposed to all go in a .c file and reference the .h stuff above
// This is the actual implementation of the functions declared above
double factorial(double n) {
    // 0! = 1 so just return it
    if(n == 0) {
        return 1;
    }
    // Recursively call factorial with n-1 until n == 0
    return n * (factorial(n - 1));
}


double power(double n, double power) {
    double result = n;
    // Loop as many times as the power and just multiply itself power amount of times
    for(int i = 1; i < power; i++) {
        result = n * result;
    }
    return result;
}

double sine(double n) {
    double result = n;
    double coefficent = 3.0; // Increment this by 2 each loop

    for(int i = 0; i < 10; i++) { // Change 10 to go out to more/less terms
        double pow = power(n, coefficent);
        double frac = factorial(coefficent);
        printf("Loop %d:\n%2.3f ^ %2.3f = %2.3f\n", i, n, coefficent, pow);
        printf("%2.3f! = %2.3f\n", coefficent, frac);

        // Switch between adding/subtracting
        if(i % 2 == 0) { // If the index of the loop is divided by 2, the index is even, so subtract
            result = result - (pow/frac); // x - ((x^3)/(3!)) - ((x^5)/(5!))...
        } else {
            result = result + (pow/frac); // x - ((x^3)/(3!)) + ((x^5)/(5!))...
        }
        coefficent = coefficent + 2;
        printf("Result = %2.3f\n\n", result);
    }
    return result;
}


// main starting point. This is suppossed to #include "functions.c" which contain the above functions in it
int main( void )
{
    double number = atof("6");
    double sineResult = sine(number);
    printf("%1.10f", sineResult);
    return (0);
}

答案 2 :(得分:0)

泰勒展开的误差取决于参数范围以及泰勒展开的顺序。我相信你已经超越了论证的界限。有关更多示例,请参见此处:www.dotancohen.com/eng/taylor-sine.php