在没有Math.sin功能的Java中实现Sine
我试图在没有使用Math.sin(x)
的Java中实现正弦函数。所以我试图用泰勒系列来实现这一点。不幸的是,这段代码给出了错误的结果。在没有Math.sin功能的Java中实现Sine
如果你不知道泰勒级数是什么,看看:
下面的代码片段,我创建:
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;
}
我不能发现我犯的错误。你做?
你的代码有两个主要问题。第一个问题是,您正在从0
循环i
到a
。这意味着,如果a
是负值,则for
循环甚至不会启动,并且结果将始终为1.0
。而如果a
是肯定的,则循环开始,但在迭代后停止,并且它没有多大意义,因为当迭代n倾向于无穷大时,泰勒apporximation可以正常工作。
第二个主要问题是您没有对输入值a
进行足够的控制。 正如我在Python: Calculate sine/cosine with a precision of up to 1 million digits
真正的泰勒展开中X中心已经说是:
其中Rn中是Lagrange余
注意Rn中尽快从中心 X0X移开增长较快。
既然你正在实施麦克劳林系列(以0为中心的泰勒级数 ),而不是一般的泰勒级数,你的函数 将尝试计算罪当给真正错误的结果(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;
}
您的问题是您正在使用正弦函数的分析值作为分母的限值。泰勒级数被评估为函数的极限接近无穷大。在这种情况下,您只是对输入值的大小进行评估,这并不合理。您应该将for
循环比较替换为i < x
,其中x是一个表示您希望生成的精度的常量(该函数对于低至20左右的值来说相当准确)。
事实上,当你在某个点上增加'x'函数开始失去精度时,因为数字的有限表示变得越来越不精确。 – talex
你期望什么样的结果,而你是怎么得到?你到目前为止做了哪些调试? –
为什么术语的数量取决于'a'的值?这与你提供的泰勒展开不一致。 – bradimus
问题出在'i talex