基于泰勒级数的余弦计算代码为何对大于90度的角失效?
问题分析与修复:手动实现余弦函数的错误排查
你的代码核心问题在于分母的更新逻辑错误,导致泰勒展开式的后续项计算完全偏离了正确形式,无法收敛到cos(π)的正确值-1。
错误细节
余弦的泰勒展开式为:
cos(x) = 1 - x²/2! + x⁴/4! - x⁶/6! + ... + (-1)ⁿx^(2n)/(2n)! + ...
每一项的分母是**(2n)!**(双阶乘),也就是后一项的分母是前一项分母乘以(2n)*(2n-1)。但你的代码中使用了:
denominator = denominator * (denominator+1) * (denominator+2);
这完全错误:比如初始分母是2(2!),第一次循环后得到2*3*4=24(正确的4!),但第二次循环会计算24*25*26=15600,而正确的6!应该是720,这直接导致后续所有项的数值完全错误,无法正确收敛。
修复后的代码
方案1:修正分母更新逻辑(贴近你的原始代码结构)
// Program to find cos x using loop. #include <stdio.h> #define _USE_MATH_DEFINES #include <math.h> double cosine(double); int main() { double x; printf("Enter angle in degrees: "); scanf("%lf", &x); x = x*M_PI/180.0; printf("The value of cos(%lf) is %lf\n", x, cosine(x)); } double cosine(double x) { double previous, current = 1; double denominator = 1*2; // 初始为2! double numerator = x*x; double sign = -1; int current_even = 2; // 当前项对应的偶数次方的阶乘基数 while(1) { previous = current; current = current + ((numerator)/(denominator))*sign; // 正确更新分母:下一个阶乘是 (current_even+2)! = current_even! * (current_even+1)*(current_even+2) current_even += 2; denominator = denominator * current_even * (current_even - 1); numerator = numerator*x*x; sign = -sign; if (fabs(previous - current)<=0.0001) { break; } } return current; }
方案2:更简洁的项迭代方式(推荐)
这种方式直接通过前一项推导后一项,避免单独维护分子分母,逻辑更清晰,同时加入了角度归一化加速收敛:
double cosine(double x) { double previous, current = 1.0; // 先将x归一到[-π, π],利用余弦的周期性和奇偶性,加速收敛 x = fmod(x, 2 * M_PI); if (x > M_PI) { x -= 2 * M_PI; } else if (x < -M_PI) { x += 2 * M_PI; } double term = 1.0; int n = 0; while (1) { previous = current; n += 2; // 下一项 = 前一项 * (-x²)/(n*(n-1)) term = term * (-1) * x * x / (n * (n - 1)); current += term; if (fabs(previous - current) <= 0.0001) { break; } } return current; }
效果验证
输入180度时,x转换为π弧度,修复后的代码会正确计算泰勒级数,最终收敛到接近-1的结果(受0.0001精度限制,结果会是-0.9999或更接近的值)。
内容的提问来源于stack exchange,提问作者user21119910
相关产品推荐
相关产品推荐

