C++计算余弦泰勒级数时n大于15返回nan问题求助
问题成因
- 无符号整型阶乘溢出:你使用的
unsigned int类型最大可存储值为4294967295,而13! = 6227020800已经超过该上限,无符号整数溢出会发生值回卷,得到非预期的极小值甚至0,后续运算出现除0错误,最终返回nan。即便换用更大的整型比如unsigned long long,20!就会达到其存储上限,依然无法支撑n到100的计算需求。 - 分开计算幂次和阶乘的冗余风险:单独计算
pow(x, 2*i)和阶乘的方式,即便不出现整型溢出,当x较大时也容易出现分子分母的数值超出浮点精度范围的问题,引入额外精度损失。 - 补充:
pow(-1, i)的写法效率较低,不过不是触发nan的核心原因。
解决办法
核心思路是通过前一项迭代推导后一项的值,避免单独计算阶乘和高次幂,从根源上解决溢出问题:
观察级数的项的规律,第i项和第i-1项的关系为:a_i = a_{i-1} * (-x²) / (2i * (2i - 1))
其中初始项a₀ = 1,累加和初始值为1,每次迭代计算当前项后更新累加和即可。
修正后的代码如下:
#include <iostream> #include <iomanip> #include <cmath> using namespace std; double exFive(int n, double x) { double sum = 1.0; double term = 1.0; // 存储当前项的值,初始为第0项1 double x_sq = x * x; // 提前计算x的平方,避免重复运算 for (int i = 1; i <= n; ++i) { term = term * (-x_sq) / ((2 * i - 1) * 2 * i); sum += term; // 可选优化:当项的绝对值小于double精度阈值时提前终止循环 // if (fabs(term) < 1e-15) break; } return sum; } void fiveIO() { int n = 1; double x; cout << "Input n: "; cin >> n; while ((n < 1) || (n > 100)) { cout << "Wrong number, input again: "; cin >> n; } cout << "Input x: "; cin >> x; cout << "Result is " << fixed << setprecision(2) << exFive(n, x); } int main() { fiveIO(); return 0; }
修正后的代码完全移除了阶乘计算逻辑,无整型溢出风险,运算过程都是浮点小数乘除,不会出现大数溢出问题,n到100也可以正常计算,同时减少了pow函数调用,运算效率更高,精度也更稳定。
内容的提问来源于stack exchange,提问作者danee
相关产品推荐
相关产品推荐

