在没有使用math.h且仅在int main()内部的C编程中,cos x和sin x的Taylor系列展开

我正在为我们学校的一个项目工作,我们需要创建一个程序来计算sin xcos x的泰勒展开系列的近似值,只使用并且没有int main()之外的用户定义函数int main() ,从-180180的所有角度,增量为+5 。 以下是我的代码:

 #include  #define PI 3.141592653589 #define NUMBER_OF_TERMS 10 int main() { int cosctr, sinctr; double ctr, radi; double cosaccu, costerm, sinaccu, sinterm; for (ctr = -180; ctr < 185; ctr = ctr + 5) { radi = ctr * PI/180.0; cosctr = 1; cosaccu = 1; costerm = 1; sinctr = 2; sinaccu = radi; sinterm = radi; while (cosctr <= 2*NUMBER_OF_TERMS) { costerm = costerm*(-1)*(radi*radi)/(cosctr*(cosctr + 1)); cosaccu = cosaccu + costerm; cosctr+=2; } do { sinterm = sinterm*(-1)*(radi*radi)/(sinctr*(sinctr + 1)); sinaccu = sinaccu + sinterm; sinctr+=2; } while (sinctr <= 2*NUMBER_OF_TERMS); printf("%.2lf %.12lf %.12lf %.12lf\n", ctr, radi, cosaccu, sinaccu); } return 0; } 

上面的代码对于15项扩展近似是准确的。 但是,如果我将NUMBER_OF_TERMS更改为例如5或10,则近似值存在缺陷。
有什么建议?

让我澄清一下:我需要获得5个术语,10个术语和15个术语的近似值。 除了之外,我不能使用任何其他库。 我不能使用int main()之外的任何其他函数(我为之前解释的模糊性道歉)。
请使用随附的更正代码进行回答。

高度进动的关键,然而简单计算sind(degrees)cosd(degrees)是首先将度数范围减小到0到90(或甚至0到45),使用通常的度数排列的三角调整。

排量:
angle = fmod(angle, 360) // reduce(-360..360)或使用a = a – (int)(a / 360)
sin(x) = -sin(-x) //减少到[0..360]
cos(x) = cos(-x) //减少到[0..360)
sin(x) = -sin(x-180) //减少到[0..180]
cos(x) = -cos(x-180) //减少到[0..180]
sin(x) = cos(90-x) //减少到[0..90]
进一步减少:
对于[45-90],使用sin(x) = cos(90-x) //减少到[0..45]

然后转换为弧度并使用泰勒级数展开。

注意:由于代码处理的是double精度,通常是17位精度,因此无需使用过程PI近似。

 // #define PI 3.141592653589 #define PI 3.1415926535897932384626433832795 

我试过你的代码; 它对我来说很好,因为它完成了它的设计目的。 下面是代码在5和10项下的余弦输出与Mathematica计算的相同近似值之间的比较。 他们同意<10^-12 ,即你的输出精度:

在此处输入图像描述

我在您的代码中看到的唯一问题是,根据您设计循环的方式,如果计算扩展中的第一个项(即余弦的常数项,即线性),您实际上会考虑NUMBER_OF_TERMS + 1项正则的术语。)从第一个学期开始,然后你的循环添加另一个NUMMBER_OF_TERMS术语。 如果这不是设计的,那么您实际上是以您期望的更高精度逼近函数。

根据其定义,泰勒级数是无穷级数项的总和。

因此,泰勒有限展开仅是真实结果的近似:随着项数的增加,该近似的精度提高。

如果有足够的术语,则某些点的近似误差变得不明显。 但是,如果尝试降低术语数,则会增加近似误差并进行检测。

在您的情况下,近似误差低于NUMBER_OF_TERMS = 15的检测阈值,但在NUMBER_OF_TERMS = 10或更低时变得明显。

随着x的增加,sin(x)和cos(x)的泰勒展开需要更长的时间收敛。 但由于这些是周期性函数,因此实际上不需要为0-90°范围之外的值扩展系列。

对于此范围之外的x值,请使用以下标识:

 sin(x) = -sin(x+180°) = -sin(-x) = sin(180°-x) cos(x) = -cos(x+180°) = cos(-x) = -cos(180°-x) 

例如,sin(175°)= sin(5°),cos(-120°)= -cos(60°)

我在另一个用户的帮助下弄清楚了。 结果我正在计算术语+ 1,使得答案比预期更准确。 在15个学期之后,这些变化超过了第12个小数点,因此没有显示结果。

 #include  #define PI 3.141592653589 #define NUMBER_OF_TERMS 10 // 5 and 15 work as well int main() { int cosctr, sinctr; double ctr, radi; double cosaccu, costerm, sinaccu, sinterm; // accu will be final answer, term will be added to accu for (ctr = -180; ctr < 185; ctr+=5) { // for loop; ctr initialized at -185 and added to in increments of 5 to produce degrees radi = ctr * PI/180.0; // calculation for radians (assigned to radi) cosctr = 1; // initialization for cos counter; must be included in loop to allow correct calculations of cos cosaccu = 1; // first term is 1 costerm = 1; // base term, to be multiplied with termcalc formula sinctr = 2; // initialization for sin counter; must be included in loop to allow correct calculations of sin sinaccu = radi; // first term is x, or degrees in radians (radi) sinterm = radi; // base term for sin // cos calculation while (cosctr < 2*NUMBER_OF_TERMS-1) { // accuracy check, 2* since increments of 2; NOTE: actual values are (1, 3, 5,...) costerm = costerm*(-1)*(radi*radi)/(cosctr*(cosctr + 1)); // TERMCALC FORMULA; multiplying previous term with formula creates next term cosaccu = cosaccu + costerm; // addition of new term to previous sum; dependent on accuracy (NUMBER_OF_TERMS) cosctr+=2; } do { // sin calculation; identical to cos, albeit with substituted vars sinterm = sinterm*(-1)*(radi*radi)/(sinctr*(sinctr + 1)); sinaccu = sinaccu + sinterm; sinctr+=2; } while (sinctr < 2*NUMBER_OF_TERMS-1); // accuracy check, 2* since increments of 2; NOTE: actual values are (2, 4, 6,...) printf("%.2lf\t%.12lf\t%.12lf\t%.12lf\n", ctr, radi, cosaccu, sinaccu); // final display; /t used for convenience } return 0; // finally!!! }