Java中不依赖Math.sin()实现正弦函数:公式报错求助
修复你的正弦泰勒展开实现问题
看起来你是想用泰勒级数展开来实现正弦函数,但代码里的几项核心逻辑出了问题,导致结果错误。先帮你梳理下正弦的泰勒展开公式,再一步步修正代码:
首先,正弦函数的泰勒展开(以0为中心的麦克劳林级数)是这样的:
sin(x) = x - x³/3! + x⁵/5! - x⁷/7! + ... + (-1)^k * x^(2k+1)/(2k+1)!
其中x是弧度值,k从0开始,precision应该指的是展开的项数(或者最高次幂的阶数)。
你的代码里的核心问题:
- 初始值错误:
answer的初始值应该是x(泰勒展开的第一项),而不是1;power的初始值也不符合项的分子规律 - 幂次计算逻辑错误:你写的
power = (power * x * x *-1) +1完全偏离了泰勒项的幂次变化,正确的做法是每次乘以-x²来得到下一项的分子 - 阶乘计算错误:
factorial = (factorial * (n +1))* (n-1)的逻辑混乱,应该每次乘以后续的两个连续整数(比如从3!到5!,需要乘4和5) - 循环步长错误:n应该每次加2,因为我们只需要奇数阶的项
修正后的代码:
public static double sin(double x, int precision) { // 初始值为泰勒展开的第一项:x double answer = x; // 当前项的分子:初始是x,之后每次乘以 -x² double currentTermNumerator = x; // 当前项的分母:初始是1! = 1,之后每次乘以下两个连续整数 double currentTermDenominator = 1; // k表示当前项的索引,从1开始(因为第一项已经加入answer了) int k = 1; // 循环到指定的精度,这里precision指展开的项数(比如precision=3就计算前3项:x, -x³/3!, x⁵/5!) while (k < precision) { // 更新分子:乘以 -x² 得到下一项的分子 currentTermNumerator *= -x * x; // 更新分母:乘以 (2k) * (2k + 1),比如k=1时,2*1=2,2*1+1=3,1!*2*3=3!;k=2时,4*5,3!*4*5=5! currentTermDenominator *= (2 * k) * (2 * k + 1); // 将当前项加入结果 answer += currentTermNumerator / currentTermDenominator; k++; } return answer; }
额外优化建议:
- 先对输入的x做角度归一化:因为正弦函数是周期为2π的周期函数,你可以先把x转换成[-π, π]范围内的弧度值,这样泰勒展开的收敛速度会更快,结果也更准确
- 可以用绝对值判断终止条件,而不是固定的precision:比如当当前项的绝对值小于某个阈值(比如1e-10)时就停止循环,这样能更灵活地控制精度
举个测试例子:
public static void main(String[] args) { // 30度转换成弧度是π/6 ≈0.5235987756 double rad = Math.PI / 6; // 用5项精度计算 double mySin = sin(rad, 5); // 对比Math.sin的结果 double actualSin = Math.sin(rad); System.out.println("我的实现结果:" + mySin); // 应该接近0.5 System.out.println("Math.sin结果:" + actualSin); // 0.5 }
这样修改后,你的正弦函数应该就能得到正确结果了。
内容的提问来源于stack exchange,提问作者Jesmar Scicluna
相关产品推荐
相关产品推荐

