假设 , t
,a
都是b
双精度(IEEE Std 754)变量,并且 , 的两个值a
都不b
是NaN
(但可能是Inf
)。之后t = a - b
,我一定有a == b + t
吗?
3 回答
绝对不。一个明显的例子是a=DBL_MAX
,b=-DBL_MAX
。那么t=INFINITY
,b+t
也是如此INFINITY
。
可能更令人惊讶的是,在某些情况下发生这种情况而没有任何溢出。基本上,它们都是a-b
不精确的形式。例如,如果a
isDBL_EPSILON/4
和b
is -1
,a-b
则为 1(假设默认舍入模式),a-b+b
然后为 0。
我提到第二个示例的原因是,这是强制舍入到 IEEE 算术中特定精度的规范方法。例如,如果您有一个 [0,1) 范围内的数字,并且想要强制将其四舍五入到 4 位精度,您可以先加然后减0x1p49
。
在执行第一个操作的过程中,位可能已经从结果的低端丢失。所以一个问题是,第二次操作会完全重现这些损失吗?我还没有完全想到这一点。
但是,当然,第一个操作可能溢出到 +/-infinity,导致第二个比较不相等。
(当然,在一般情况下,使用==
浮点值几乎总是一个错误。)
使用浮点数时,您无法得到任何保证。如果两个数字的指数不同,则算术运算的结果可能无法完全用浮点数表示。
考虑这段代码:
float a = 0.003f;
float b = 10000000.0f;
float t = a - b;
float x = b + t;
在 Visual Studio 2010 上运行,您将t==-10000000.0f
获得x==0
.
在比较浮点数时,永远不要使用相等。而是比较两个值之间差异的绝对值和一个足够小的满足您的精度需求的 epsilon 值。
它变得更加奇怪,因为不同的浮点实现可能会为相同的操作返回不同的结果。