在没有Math.sin函数的情况下在Java中实现正弦
我试图在Java中实现正弦函数,而不使用在没有Math.sin函数的情况下在Java中实现正弦,java,trigonometry,Java,Trigonometry,我试图在Java中实现正弦函数,而不使用Math.sin(x)。所以我想用泰勒级数来实现这一点。不幸的是,此代码给出了错误的结果 如果您不知道泰勒级数是什么,请查看: 以下是我创建的代码片段: public static double sin(double a) { double temp = 1; int denominator = -1; if(a == Double.NEGATIVE_INFINITY || !(a < Double.POSITIVE_INFINI
Math.sin(x)
。所以我想用泰勒级数来实现这一点。不幸的是,此代码给出了错误的结果
如果您不知道泰勒级数是什么,请查看:
以下是我创建的代码片段:
public static double sin(double a) {
double temp = 1;
int denominator = -1;
if(a == Double.NEGATIVE_INFINITY || !(a < Double.POSITIVE_INFINITY)) {
return Double.NaN;
}
if(a != 0) {
for (int i = 0; i <= a; i++) {
denominator += 2;
if(i % 2 == 0) {
temp = temp + (Math.pow(a, denominator) / Factorial.factorial(denominator));
} else {
temp = temp - (Math.pow(a, denominator) / Factorial.factorial(denominator));
}
}
}
return temp;
}
公共静态双sin(双a){
双温=1;
int分母=-1;
如果(a==Double.NEGATIVE | | |!(a 对于(int i=0;i您的问题是使用正弦函数要计算的值作为分母的极限。泰勒级数是在函数的极限接近无穷大时计算的。在这种情况下,您只对输入值的大小进行计算,这没有实际意义。您应该替换用于
与i
进行循环比较,其中x是一个常数,表示您希望使其精确到的程度(对于低至20左右的值,该函数将相当精确).您的代码中有两个主要问题。第一个问题是,您正在将i
从0
循环到a
。这意味着,如果a
为负值,那么for
循环甚至不会启动,您的结果将始终是1.0
。而如果a
为正值,则循环开始,但它在(int)a
迭代之后停止,这没有多大意义,因为当迭代n趋于无穷大时,泰勒近似可以很好地工作
第二个主要问题是您没有对输入值a
进行足够的控制。
正如我在书中已经说过的
以x0为中心的真实泰勒展开式为:
其中Rn是拉格朗日余数
请注意,当x离开中心时,Rn增长很快
x0
由于您正在实施麦克劳林级数(泰勒级数
以0为中心,而不是一般的泰勒级数
当试图计算的sin(x)为
x的大值
因此,在for
循环之前,您必须将域减少到至少[-pi,pi]。如果您将其减少到[0,pi],并利用正弦奇偶校验,效果会更好
工作代码:
public static double sin(double a) {
if (a == Double.NEGATIVE_INFINITY || !(a < Double.POSITIVE_INFINITY)) {
return Double.NaN;
}
// If you can't use Math.PI neither,
// you'll have to create your own PI
final double PI = 3.14159265358979323846;
// Fix the domain for a...
// Sine is a periodic function with period = 2*PI
a %= 2 * PI;
// Any negative angle can be brought back
// to it's equivalent positive angle
if (a < 0) {
a = 2 * PI - a;
}
// Also sine is an odd function...
// let's take advantage of it.
int sign = 1;
if (a > PI) {
a -= PI;
sign = -1;
}
// Now a is in range [0, pi].
// Calculate sin(a)
// Set precision to fit your needs.
// Note that 171! > Double.MAX_VALUE, so
// don't set PRECISION to anything greater
// than 84 unless you are sure your
// Factorial.factorial() can handle it
final int PRECISION = 50;
double temp = 0;
for (int i = 0; i <= PRECISION; i++) {
temp += Math.pow(-1, i) * (Math.pow(a, 2 * i + 1) / Factorial.factorial(2 * i + 1));
}
return sign * temp;
}
公共静态双sin(双a){
如果(a==Double.NEGATIVE | | |!(aPI){
a-=PI;
符号=-1;
}
//现在a在[0,pi]范围内。
//计算sin(a)
//设置精度以满足您的需要。
//注意171!>Double.MAX_值,所以
//不要将精度设置为更高的值
//除非你确定你的
//Factorial.Factorial()可以处理它
最终整数精度=50;
双温=0;
对于(int i=0;i)你期望得到什么结果,你得到了什么?到目前为止你做了什么调试?为什么术语的数量取决于a
的值?这与你提供的泰勒展开不一致。问题在于i例如:sin(1)=001745…;但我的函数是:1.158529…;即使在我做了之后,事实上,当你在某个点增加你的x
时,函数开始失去精度,因为数字的有限表示变得越来越不精确。