说,内存中有两个不断递增的浮点数,我们记作 a 和 b。
程序不断运行的过程中,有两种操作会递增这两个数:
- 给 a 加上一个非负浮点数
- 给 a 和 b 同时加上一个非负整数
同时,后台有一个线程在不断向服务器以差值的形式上报 a 和 b 的增量。流程是:
deltaA = a - lastA
deltaB = b - lastB
report(deltaA, deltaB)
lastA = a
lastB = b
那么问题来了,服务端收到的 deltaA 和 deltaB 有没有可能出现 deltaA < deltaB 的情况呢?这里我们只考虑浮点数的精度问题,不考虑其他因素,比如线程调度等等。
显然既然写这个,答案肯定是有可能。
不过这看起来很奇怪,因为 a 和 b 的增量都是非负的,而且 a 每次的增量只会比 b 大不可能比 b 小。但是,浮点数的精度问题可能会导致这种情况发生。
问题就出在每次上报的差值运算。lastA 和 a 都是不断累加出来的,可能都有精度误差,并且误差舍入的方向可能不同,如果lastA 的误差方向是向上的,而 a 的误差方向是向下的,那么 deltaA 就可能比 deltaB 小。
直观的例子:
lastA = 2000000.300000000005
lastB = 1000000.0
执行操作 2,a 和 b 同时加上 120.0 后
a = 2000120.300000000004
b = 1000120.0
此时计算 delta 理应都是 120,但由于精度丢失 deltaA 会偏小。
deltaA = a - lastA = 119.999999999999
deltaB = b - lastB = 120.0