好的所以我正在做一个程序,我试图让右侧的结果相当于左侧,精度为0.0001%
sin x = x - (x ^ 3)/ 3! +(x ^ 5)/ 5! +(x ^ 7)/ 7! + ...
#include<iostream>
#include<iomanip>
#include<math.h>
using namespace std;
long int fact(long int n)
{
if(n == 1 || n == 0)
return 1;
else
return n*fact(n-1);
}
int main()
{
int n = 1, counts=0; //for sin
cout << "Enter value for sin" << endl;
long double x,value,next = 0,accuracy = 0.0001;
cin >> x;
value = sin(x);
do
{
if(counts%2 == 0)
next = next + (pow(x,n)/fact(n));
else
next = next - (pow(x,n)/fact(n));
counts++;
n = n+2;
} while((fabs(next - value))> 0);
cout << "The value of sin " << x << " is " << next << endl;
}
让我说我为x输入45
我得到了结果
sin 45的值为nan。
任何人都可以帮我解决我做错的事吗?
答案 0 :(得分:2)
首先你的状况应该是
while((fabs(next - value))> accuracy)
和fact
应该返回long double
。
当你改变它仍然不会为45
的价值工作。原因是这个泰勒级数对于大值收敛得太慢。
这是公式中的错误术语
这里k是迭代次数a=0
,函数是sin
。为了使条件变为假45^(k+1)/(k+1)!
次,绝对值为sin
或{ {1}}(取决于第k个导数)(它在0和1之间)应小于cos
。
在这个值为50的公式中,数字仍然非常大(我们应该预期误差大约为1.3 * 10 ^ 18,这意味着我们肯定会做超过50次迭代)。
0.0001
和45^50
会溢出,然后将它们分开会给你50!
。
在您的原始版本infinity/infinity=NAN
中,值不适合整数(您的值溢出到fact
),然后0
上的除法会给出无穷大,在减去另一个无穷大之后你0
。
答案 1 :(得分:0)
我引用here关于pow
:
返回值
如果没有发生错误,则将基数提升到exp的幂(或 iexp)(baseexp),返回。
如果发生域错误,请执行 返回实现定义的值(支持的NaN )
如果由于溢出而发生极点错误或范围错误,则为±HUGE_VAL,
如果由于发生范围错误 下溢,返回正确的结果(舍入后)。
进一步阅读:
错误处理
...
除了上面指定的地方,如果任何参数是NaN,则返回NaN
所以基本上,因为n
正在增加并且你有很多循环pow
返回NaN
(你使用的编译器显然支持它)。其余的是算术。你用溢出值来计算。
我相信你试图通过使用泰勒系列来近似sin(x)
。我不确定这是否可行。
也许你可以在点击NaN
后立即尝试停止循环,而不是更新变量next
并输出。这是你可以得到的最接近你的算法。
答案 2 :(得分:0)
如果您使用任何合理级别的警告编译了系统,您会立即看到您没有使用变量accuracy
。这个以及fact
函数返回long int
的事实只是问题的一小部分。即使你纠正了这些问题,使用你的算法也不会得到sin(45)
的好结果。
问题在于x=45
,sin(x)
的泰勒扩展中的术语开始逐渐减少,直到n=45
。这是一个很大的问题,因为45 45 / 45!是一个非常大的数字,2428380447472097974305091567498407675884664058685302734375/1171023117375434566685446533210657783808,或大约2 * 10 18 。你的算法最初会添加和减去只有在20多次加法/减法后开始减少的大数字,最终希望结果介于-1和+1之间。考虑到输入值为45并使用本机浮点类型,这是一个不可实现的希望。
你可以使用一些BigNum
类型(互联网充满了它们)和你的算法,但是当你只需要四个位置的准确性时,那就太极端了。或者,您可以利用sin(x)
,sin(x+2*pi)=sin(x)
的周期性。输入值45等于1.017702849742894661522992634 ...(模2 * pi)。您的算法非常适合输入1.017702849742894661522992634。
你可以做得更好,但是以2 * pi为模的输入值是计算正弦和余弦的合理算法的第一步。更好的是,您可以使用sin(x+pi)=-sin(x)
的事实。这使您可以将-infinity到+ infinity的范围缩小到0到pi。更好的是,你可以使用0和pi之间的事实,sin(x)
关于pi / 2是对称的。你可以做得更好。三角函数的实现极大地利用了这些行为,但它们通常不使用泰勒近似。