泰勒级数计算负x对应e^x时绝对误差过大原因咨询
误差原因说明
你观察到的负x计算误差不是常规精度不足导致,核心原因是符号交替级数的大数相消误差:
- 当x为负值时,ex的泰勒展开项为正负交替形式,项的绝对值会先上升到与e|x|相当的量级,之后才逐渐衰减到截断阈值以下
- 以x=-40为例,展开项的峰值绝对值可达~2e16,与双精度浮点数的有效位数上限(约16位十进制有效数字)相当,多个极大的正负项相加抵消得到仅为1e-18量级的最终结果时,有效数字会被完全抵消,最终输出完全失去参考价值
修复方案
你提到的e^(-x) = 1 / e^|x|转换是最高效的修复方案,只需在原函数入口增加负x分支即可,修改后代码如下:
#include <stdio.h> #include <math.h> double Exp(double x); int main(void) { double x; printf("x="); scanf("%le", &x); printf("%le", Exp(x)); return 0; } double Exp(double x) { // 负指数转换为正指数计算后取倒数,避免大数相消 if (x < 0) { return 1.0 / Exp(-x); } double h, eps = 1.e-16, Sum = 1.0; int i = 2; h = x; do { Sum += h; h *= x / i; i++; } while (fabs(h) > eps); return Sum ; }
修改后测试结果:
- x=-40时输出约4.24835e-18,与真实值一致
- x=-50时输出约1.92875e-22,误差回到双精度浮点数的正常范围内
可选进阶优化
如果需要覆盖更大的x范围、降低计算量,可以增加指数范围规约逻辑:将x拆分为x = k * ln2 + r(k为整数,r落在[-ln2/2, ln2/2]区间内),利用e^x = 2^k * e^r的性质,仅对绝对值很小的r做泰勒展开,可大幅减少所需的展开项数,进一步提升计算效率和精度。
内容的提问来源于stack exchange,提问作者Nickie
相关产品推荐
相关产品推荐

