泰勒级数 - 计算 sin(x) 直到 6 位精度
Taylor series - calculating sin(x) until 6 digits precision
我必须用泰勒级数计算 sin(x),直到输出有 6 位小数。参数是一个角度。我没有实现检查小数位,我只是打印下一个值(以检查它是否有效),但在 10-20 次迭代后它显示 infinities/NaN。
我的想法有什么问题吗?
public static void sin(double x){
double sin = 0;
int n=1;
while(1<2){
sin += (Math.pow(-1,n) / factorial(2*n+1)) * Math.pow(x, 2*n+1);
n++;
try {
Thread.sleep(50);
} catch (InterruptedException ex) {
}
// CHECKING THE PRECISION HERE LATER
System.out.println(sin);
}
}
等式:
问题:
NAN 错误通常是一个非常大的数字,如果您将 2 个数字相除但除数很小或为零,就会发生这种情况。
解决方案
发生这种情况是因为你的阶乘数溢出了,后来在某个时候你又被零除了
如果您的阶乘被作为 int 参数,则将其更改为 BIgInterger
对象。
不要使用阶乘和幂来计算每一项!你会迅速溢出。
只需意识到下一项是 -term * x * x / ((n+1)*(n+2)) ,其中 n 每一项增加 2:
double tolerance = 0.0000007; // or whatever limit you want
double sin = 0.;
int n = 1;
double term = x;
while ( Math.abs(term) > tolerance ) {
sin += term;
term *= -( (x/(n+1)) * (x/(n+2)) );
n+= 2;
}
要补充@Xoce(和@FredK)提供的答案,请记住您正在计算麦克劳林级数(泰勒的特例 x = 0
)。虽然这对于零的 pi/2
范围内的值会相当快地收敛,但对于 x
更远的值,您可能无法在阶乘爆炸之前收敛数字。
我的建议是使用关于 sin(x)
的最接近值的实际泰勒级数,其确切值已知(即,最接近 pi/2
的倍数,而不仅仅是零。并且一定要做收敛检查!
我必须用泰勒级数计算 sin(x),直到输出有 6 位小数。参数是一个角度。我没有实现检查小数位,我只是打印下一个值(以检查它是否有效),但在 10-20 次迭代后它显示 infinities/NaN。
我的想法有什么问题吗?
public static void sin(double x){
double sin = 0;
int n=1;
while(1<2){
sin += (Math.pow(-1,n) / factorial(2*n+1)) * Math.pow(x, 2*n+1);
n++;
try {
Thread.sleep(50);
} catch (InterruptedException ex) {
}
// CHECKING THE PRECISION HERE LATER
System.out.println(sin);
}
}
等式:
问题:
NAN 错误通常是一个非常大的数字,如果您将 2 个数字相除但除数很小或为零,就会发生这种情况。
解决方案
发生这种情况是因为你的阶乘数溢出了,后来在某个时候你又被零除了
如果您的阶乘被作为 int 参数,则将其更改为 BIgInterger
对象。
不要使用阶乘和幂来计算每一项!你会迅速溢出。 只需意识到下一项是 -term * x * x / ((n+1)*(n+2)) ,其中 n 每一项增加 2:
double tolerance = 0.0000007; // or whatever limit you want
double sin = 0.;
int n = 1;
double term = x;
while ( Math.abs(term) > tolerance ) {
sin += term;
term *= -( (x/(n+1)) * (x/(n+2)) );
n+= 2;
}
要补充@Xoce(和@FredK)提供的答案,请记住您正在计算麦克劳林级数(泰勒的特例 x = 0
)。虽然这对于零的 pi/2
范围内的值会相当快地收敛,但对于 x
更远的值,您可能无法在阶乘爆炸之前收敛数字。
我的建议是使用关于 sin(x)
的最接近值的实际泰勒级数,其确切值已知(即,最接近 pi/2
的倍数,而不仅仅是零。并且一定要做收敛检查!