C语言中近似相等浮点值相减得非零结果,是否可视为零?
问题描述
我正在用C语言计算一个数学表达式,表达式如下:
以下是我编写的计算代码:
int main() { double x,y,A1,B1,C1,result; x = 8.1500e-07; y = 7.9714e-08; A1 = (1-exp(-2*x))/(2*x); B1 = 2/(x*( 1 + pow((y/x),2)) ); C1 = 1 - ( exp(-x)*( cos(y) - (y/x)*sin(y) )); result = 1 + A1 - B1*C1; printf("1 + A1 = %e\n",1+A1); printf("B1*C1 = %e\n",B1*C1); printf("result = %e\n",result); }
运行后发现,单独打印的1+A1和B1*C1看起来数值相等,但两者相减得到一个极小的负值,运行结果如下:
我想知道:这个结果是否属于计算误差(类似实验误差),可以安全地认为结果是零?还是我哪里忽略了问题?
分析与结论
这个极小的负值确实是浮点数计算的舍入误差,完全可以视为零,理由如下:
- 从数值量级看,结果是
-2.22e-16,而double类型的机器epsilon(即浮点数能区分的最小非零差值)约为2.22e-16,说明两个值的差异已经达到了double精度的极限,属于正常的舍入误差范畴。 - 你的计算逻辑没有问题,当两个几乎完全相等的浮点数相减时,很容易出现这种量级的偏差——因为浮点数的有效位数有限,无法精确表示所有实数,计算过程中的累计舍入操作会导致最终出现极小的偏差。
- 从数学理论推导来看,如果表达式本身等价,
1+A1和B1*C1应该严格相等,所以这个极小的负值完全是计算精度限制导致的,并非逻辑错误。
如果需要更严谨的结果输出,可以在代码中添加阈值判断,比如当结果的绝对值小于1e-12时,直接输出0。
内容的提问来源于stack exchange,提问作者bubucodex
相关产品推荐
相关产品推荐

