为何泰勒展开实现的e^x函数在x≥0.6时输出'inf'?
问题分析与解决方案
咱们来拆解下你的代码为什么在x≥0.6时会输出inf——哪怕你设置了res != res_old的终止条件,核心问题出在阶乘溢出和终止条件的触发时机上:
1. 阶乘函数的int溢出问题
你的fak函数用int类型存储阶乘结果,但int的最大值通常只有2^31-1(约21亿)。咱们算一下:
- 12! = 479001600,还在int范围内
- 13! = 6227020800,直接超出int上限,会发生溢出,变成负数或者无意义的小值
当阶乘溢出后,pow(x,k)/fak(k)的分母会变成错误值(比如负数或者极小的正数),导致这一项的数值突然变得极大,直接让res累加溢出成inf(无穷大)。这时候你的终止条件res != res_old已经没用了——因为inf和任何数值比较都是不相等的,循环会继续,但结果已经是inf了。
2. 终止条件的逻辑漏洞
你想用res != res_old判断“累加项小到无法改变double精度”从而终止循环,但这个前提是每一项的计算都是正确的。如果在触发这个条件之前,阶乘已经溢出,导致某一项突然爆炸式增长,res直接溢出到inf,那么终止条件就完全失效了。
修复后的代码
解决这个问题的关键是避免直接计算大阶乘,改用递推的方式计算每一项,这样既不会溢出,也更高效:
#include <stdio.h> #include <math.h> // 把x作为参数传入,方便测试不同值 double func_e(double x) { double res = 1.0; // k=0时的项是1,作为初始结果 double current_term = 1.0; // 当前项的初始值(k=0) int k = 1; while (1) { // 递推计算下一项:第k项 = 第k-1项 * x/k current_term *= x / k; double res_old = res; res += current_term; // 当累加后结果不再变化,说明精度已达极限,终止循环 if (res == res_old) { break; } k++; } return res; } int main(void) { printf("e^1 = %.10f\n", func_e(1.0)); printf("e^0.6 = %.10f\n", func_e(0.6)); printf("e^2.0 = %.10f\n", func_e(2.0)); // 测试更大的x值 return 0; }
修复说明
- 递推计算项:不用单独算阶乘和
pow(x,k),而是用前一项乘以x/k得到当前项,全程用double存储,能处理大得多的k值,不会轻易溢出。 - 正确的初始值:指数函数的泰勒展开第一项是k=0时的1,所以res和current_term都从1开始。
- 稳定的终止条件:现在只有当累加项小到无法改变double的精度时才会终止,不会在中途因为溢出导致错误。
这样修改后,别说x=0.6,就算x=2、x=10都能正常输出正确结果啦~
内容的提问来源于stack exchange,提问作者Builderhummel
相关产品推荐
相关产品推荐

