我试图用sine
和Taylor 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);
}
最佳答案
正如我在Python: Calculate sine/cosine with a precision of up to 1 million digits
以x0为中心的真实泰勒展开式是:
其中Rn是拉格朗日余数
注意,当x偏离中心时,Rn增长很快
x0点。
因为你在实现Maclaurin级数(Taylor级数
以0)为中心,而不是一般的泰勒级数,你的函数
在计算sin(x)时会给出错误的结果
x的大值。
所以在for
函数中的sine()
循环之前,必须将域至少减少到[-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!