我尝试创建自定义 sine
功能使用c
和 Taylor Series用于计算 sin
系列中有 10 个术语,但是当我尝试查找 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);
}
最佳答案
正如我在 Python: Calculate sine/cosine with a precision of up to 1 million digits 中所说的那样
The real Taylor expansion centered in x0 is:
where Rn is the Lagrange Remainder
Note that Rn grows fast as soon as x moves away from the center x0.
Since you are implementing the Maclaurin series (Taylor series centered in 0) and not the general Taylor series, your function will give really wrong results when trying to calculate sin(x) for big values of x.
因此,在 sine()
函数中的 for
循环之前,您必须至少将定义域减小到 [-pi, pi]。 .. 如果将它减少到 [0, pi] 并利用正弦奇偶校验,效果会更好。
要修复您的代码,您需要 fmod()
来自 math.h
,因此您可以:
#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!
关于创建自定义正弦函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48758757/