如何在 Java 中重新实现 sin() 方法? (结果接近 Math.sin() )
我知道 Math.sin()
可以工作,但我需要使用 factorial(int)
自己实现它,我已经有一个阶乘方法,下面是我的 sin 方法,但我无法获得与 Math.sin() 相同的结果:
public static double factorial(double n) {
if (n <= 1) // base case
return 1;
else
return n * factorial(n - 1);
}
public static double sin(int n) {
double sum = 0.0;
for (int i = 1; i <= n; i++) {
if (i % 2 == 0) {
sum += Math.pow(1, i) / factorial(2 * i + 1);
} else {
sum += Math.pow(-1, i) / factorial(2 * i + 1);
}
}
return sum;
}
I know Math.sin()
can work but I need to implement it myself using factorial(int)
I have a factorial method already below are my sin
method but I can't get the same result as Math.sin()
:
public static double factorial(double n) {
if (n <= 1) // base case
return 1;
else
return n * factorial(n - 1);
}
public static double sin(int n) {
double sum = 0.0;
for (int i = 1; i <= n; i++) {
if (i % 2 == 0) {
sum += Math.pow(1, i) / factorial(2 * i + 1);
} else {
sum += Math.pow(-1, i) / factorial(2 * i + 1);
}
}
return sum;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您应该使用泰勒级数。一个很棒的教程这里
我可以看到你已经尝试过,但你的sin方法不
正确计算sin 函数的工作示例。抱歉,我用 C++ 记下了它,但希望你能明白。这并没有那么不同:)
You should use the Taylor series. A great tutorial here
I can see that you've tried but your sin method is incorrect
A working example of calculating the sin function. Sorry I've jotted it down in C++, but hope you get the picture. It's not that different :)
你的公式是错误的,你得到了 sin(1) 的粗略结果,而你通过改变 n 所做的就是改变这个计算的准确性。您应该在维基百科中查找公式,您会发现您的 n 位于错误的位置,不应该用作 for 循环的极限,而应该用作分数的分子,在 Math.pow( ...) 方法。查看泰勒级数
Your formula is wrong and you are getting a rough result of sin(1) and all you're doing by changing n is changing the accuracy of this calculation. You should look the formula up in Wikipedia and there you'll see that your n is in the wrong place and shouldn't be used as the limit of the for loop but rather in the numerator of the fraction, in the Math.pow(...) method. Check out Taylor Series
看来您正在尝试使用 sin 的泰勒级数展开式,但尚未包含x 的术语。因此,无论参数如何,您的方法将始终尝试逼近 sin(1)。
方法参数仅控制精度。在良好的实现中,会自动检测该参数的合理值,从而防止调用者传递较低的值,这可能会导致大 x 的结果非常不准确。此外,为了帮助序列的快速收敛(并防止不必要的重要性损失),实现通常使用sin(x + k * 2 * PI) = sin(x) 首先将 x 移动到 [-PI, PI] 范围内。
此外,由于对阶乘的重复评估,您的方法不是很有效。 (要计算阶乘(5),您需要计算阶乘(3),您已经在 for 循环的上一次迭代中计算了阶乘(3))。
最后,请注意,您的阶乘实现接受 double 类型的参数,但仅对整数正确,并且您的 sin 方法可能应该接收 double 类型的角度。
It looks like you are trying to use the taylor series expansion for sin, but have not included the term for x. Therefore, your method will always attempt to approximate sin(1) regardless of argument.
The method parameter only controls accuracy. In a good implementation, a reasonable value for that parameter is auto-detected, preventing the caller from passing to low a value, which can result in highly inaccurate results for large x. Moreover, to assist fast convergence (and prevent unnecessary loss of significance) of the series, implementations usually use that sin(x + k * 2 * PI) = sin(x) to first move x into the range [-PI, PI].
Also, your method is not very efficient, due to the repeated evaluations of factorials. (To evaluate factorial(5) you compute factorial(3), which you have already computed in the previous iteration of the for-loop).
Finally, note that your factorial implementation accepts an argument of type double, but is only correct for integers, and your sin method should probably receive the angle as double.
(x) 可以表示为 泰勒级数:
Sin ; Sin (x) = (x/1!) – (x3/3!) + (x5/5!) - (x7/7!) + …
所以你可以这样编写你的代码:
这里我们只运行了 100 次循环。如果您想运行更多,则需要更改基本方程(否则将出现无穷大值)。
我从 RGDromey 的《如何用计算机求解》一书中学到了一个非常好的技巧。他这样解释:
(x3/3! ) = (x X x X x)/(3 X 2 X 1) &nb &nb = (x2/(3 X 2)) X (x1/1!) i = 3
(x5/5! ) = (x X x X x X x X x)/(5 X 4 X 3 X 2 X 1) &nb = (x2/(5 X 4)) X (x3/3!) i = 5
(x7/7! ) = (x X x X x X x X x X x X x)/(7 X 6 X 5 X 4 X 3 X 2 X 1) = (x< support>2/(7 X 6)) X (x5/5!) i = 7
所以项 (x2/(3 X 2)) 、 (x2/(5 X 4))、(x2/ (7 X 6)) 可以表示为
x2/(i X (i - 1)) 对于 i = 3,5,7,...
因此,要生成正弦级数的连续项,我们可以编写:
当前第 ith 项 = (x2 / ( i X (i - 1)) ) X(上一项)
代码如下:
请注意,
j
变量用于替换术语 的符号。Sin (x) can be represented as Taylor series:
Sin (x) = (x/1!) – (x3/3!) + (x5/5!) - (x7/7!) + …
So you can write your code like this:
Here we have run our loop only 100 times. If you want to run more than that you need to change your base equation (otherwise infinity value will occur).
I have learned a very good trick from the book “How to solve it by computer” by R.G.Dromey. He explain it like this way:
(x3/3! ) = (x X x X x)/(3 X 2 X 1) = (x2/(3 X 2)) X (x1/1!) i = 3
(x5/5! ) = (x X x X x X x X x)/(5 X 4 X 3 X 2 X 1) = (x2/(5 X 4)) X (x3/3!) i = 5
(x7/7! ) = (x X x X x X x X x X x X x)/(7 X 6 X 5 X 4 X 3 X 2 X 1) = (x2/(7 X 6)) X (x5/5!) i = 7
So the terms (x2/(3 X 2)) , (x2/(5 X 4)), (x2/(7 X 6)) can be expressed as
x2/(i X (i - 1)) for i = 3,5,7,…
Therefore to generate consecutive terms of the sine series we can write:
current ith term = (x2 / ( i X (i - 1)) ) X (previous term)
The code is following:
Note that
j
variable used to alternate the sign of the term .