我在一次考试中遇到了以下考试问题,如果有人可以帮助解释以下问题,我将不胜感激。
请考虑以下代码:
double a = 1.0, b = 1.0, c = 1.0e-16;
a += c;
a -= c;
b -= c;
b += c;
a和b的值是什么?
A:a和b都等于1:0。
B:a等于1:0,b小于1:0。
C:a小于1:0,b等于1:0。
D:a小于1:0,b小于1:0。
答案 0 :(得分:5)
首先,C标准未定义浮点数的确切行为和准确性。如果我们假设IEEE-754双精度浮点数,则可以这样说:
DBL_EPSILON
(约2.2e-16)定义为1与下一个更大的可表示数字之间的差。这意味着,如果您至少将DBL_EPSILON / 2
添加到1.0,则结果将更接近1.0 + DBL_EPSILON
,而不是添加到1.0,因此结果将不是1.0。对于您的代码,c
小于DBL_EPSILON / 2
,因此1.0 + c
给出1.0
。
(注意:我在这里假设舍入模式是四舍五入到最接近的数字,这是大多数实现中的默认值。其他舍入模式可以给出不同的结果)。
当您低于2的幂(例如1.0)时,浮点数的密度加倍。这意味着ε的有效值下降到其值的一半。因此,DBL_EPSILON / 4
是从1.0减去后得出不同结果的最小值。由于c > DBL_EPSILON / 4
,1.0 - c
给出了不同的结果。
这样做的结果是,a
的第一个加法将无效,但减法会改变它,因此最终的值小于1。b
将受到以下因素的影响两种操作都等于1.0。
这已由trying it out验证,并给出:
a = 0.99999999999999988898 b = 1.00000000000000000000