我一直在关注我教授给我们的指南,但我找不到我错的地方。我也经历了一些关于在C中实现泰勒系列的其他问题。
假设RaiseTo(将数字提升到x的幂)就在那里。
double factorial (int n)
{
int fact = 1,
flag;
for (flag = 1; flag <= n; flag++)
{
fact *= flag;
}
return flag;
}
double sine (double rad)
{
int flag_2,
plusOrMinus2 = 0; //1 for plus, 0 for minus
double sin,
val2 = rad,
radRaisedToX2,
terms;
terms = NUMBER_OF_TERMS; //10 terms
for (flag_2 = 1; flag_2 <= 2 * terms; flag_2 += 2)
{
radRaisedToX2 = RaiseTo(rad, flag_2);
if (plusOrMinus2 == 0)
{
val2 -= radRaisedToX2/factorial(flag_2);
plusOrMinus2++; //Add the next number
}
else
{
val2 += radRaisedToX2/factorial(flag_2);
plusOrMinus2--; //Subtract the next number
}
}
sin = val2;
return sin;
}
int main()
{
int degree;
scanf("%d", °ree);
double rad, cosx, sinx;
rad = degree * PI / 180.00;
//cosx = cosine (rad);
sinx = sine (rad);
printf("%lf \n%lf", rad, sinx);
}
所以在循环期间,我得到了rad ^ x,将其除以从1开始的奇数系列的阶乘,然后根据需要添加或减去它,但是当我运行程序时,我得到输出方式高于一,我们都知道sin(x)的极限是1和-1,我真的想知道我哪里出错所以我可以改进,抱歉,如果这是一个非常糟糕的问题。
答案 0 :(得分:3)
12!
以上的任何内容都超过32位int
,因此这些值会溢出,因此无法返回您所期望的内容。
不是每次计算全因子,而是查看序列中相对于前一个项的每个项。对于任何给定的术语,下一个术语是前一个术语的-((x*x)/(flag_2*(flag_2-1))
倍。所以从术语x
开始,然后乘以每个连续术语的因子。
在不知道你需要多少个术语的情况下,计算double
精度的结果也是一个技巧。我将此作为练习留给读者。
答案 1 :(得分:1)
在函数factorial
中,您在分配到函数的int
返回值之前进行double
乘法运算。因子可以轻易地打破int
范围,例如20! = 2432902008176640000
。
你还返回了错误的变量 - 循环计数器!
请将本地变量更改为double
,如
double factorial (int n)
{
double fact = 1;
int flag;
for (flag = 1; flag <= n; flag++)
{
fact *= flag;
}
return fact; // it was the wrong variable, and wrong type
}
此外,甚至不需要进行因子计算。请注意,系列中的每个术语都将前一个术语乘以rad
并除以术语编号 - 并更改符号。
答案 2 :(得分:0)
另一种相当天真的5分钟方法涉及计算一个包含前20个左右阶乘的查找表,即1! .. 20!这需要非常少的记忆,并且可以提高速度,而不是每次都能提高速度。计算方法。在预先计算阶乘的函数中可以很容易地实现进一步的优化,利用每个阶乘的关系。
在两个trig函数的循环中有效消除分支(如果X执行Y,否则执行Z)的方法将再次提供更高的速度。
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
const int nMaxTerms=20;
double factorials[nMaxTerms];
double factorial(int n)
{
if (n==1)
return 1;
else
return (double)n * factorial(n - 1.0);
}
void precalcFactorials()
{
for (int i=1; i<nMaxTerms+1; i++)
{
factorials[i-1] = factorial(i);
}
}
/*
sin(x) = x - (x^3)/3! + (x^5)/5! - (x^7)/7! .......
*/
double taylorSine(double rads)
{
double result = rads;
for (int curTerm=1; curTerm<=(nMaxTerms/2)-1; curTerm++)
{
double curTermValue = pow(rads, (curTerm*2)+1);
curTermValue /= factorials[ curTerm*2 ];
if (curTerm & 0x01)
result -= curTermValue;
else
result += curTermValue;
}
return result;
}
/*
cos(x) = 1 - (x^2)/2! + (x^4)/4! - (x^6)/6! .......
*/
double taylorCos(double rads)
{
double result = 1.0;
for (int curTerm=1; curTerm<=(nMaxTerms/2)-1; curTerm++)
{
double curTermValue = pow(rads, (curTerm*2) );
curTermValue /= factorials[ (curTerm*2) - 1 ];
if (curTerm & 0x01)
result -= curTermValue;
else
result += curTermValue;
}
return result;
}
int main()
{
precalcFactorials();
printf("Math sin(0.5) = %f\n", sin(0.5));
printf("taylorSin(0.5) = %f\n", taylorSine(0.5));
printf("Math cos(0.5) = %f\n", cos(0.5));
printf("taylorCos(0.5) = %f\n", taylorCos(0.5));
return 0;
}
Math sin(0.5) = 0.479426
taylorSin(0.5) = 0.479426
Math cos(0.5) = 0.877583
taylorCos(0.5) = 0.877583
在javascript中实现,当在sin / cos函数中仅对7个项求和时,代码产生看似相同的结果(我没有经常测试)到内置的Math库。
window.addEventListener('load', onDocLoaded, false);
function onDocLoaded(evt)
{
console.log('starting');
for (var i=1; i<21; i++)
factorials[i-1] = factorial(i);
console.log('calculated');
console.log(" Math.cos(0.5) = " + Math.cos(0.5));
console.log("taylorCos(0.5) = " + taylorCos(0.5));
console.log('-');
console.log(" Math.sin(0.5) = " + Math.sin(0.5));
console.log("taylorSine(0.5) = " + taylorSine(0.5));
}
var factorials = [];
function factorial(n)
{
if (n==1)
return 1;
else
return n * factorial(n-1);
}
/*
sin(x) = x - (x^3)/3! + (x^5)/5! - (x^7)/7! .......
*/
function taylorSine(x)
{
var result = x;
for (var curTerm=1; curTerm<=7; curTerm++)
{
var curTermValue = Math.pow(x, (curTerm*2)+1);
curTermValue /= factorials[ curTerm*2 ];
if (curTerm & 0x01)
result -= curTermValue;
else
result += curTermValue;
}
return result;
}
/*
cos(x) = 1 - (x^2)/2! + (x^4)/4! - (x^6)/6! .......
*/
function taylorCos(x)
{
var result = 1.0;
for (var curTerm=1; curTerm<=7; curTerm++)
{
var curTermValue = Math.pow(x, (curTerm*2));
curTermValue /= factorials[ (curTerm*2)-1 ];
if (curTerm & 0x01)
result -= curTermValue;
else
result += curTermValue;
}
return result;
}
&#13;