以下示例突出显示了使用浮点数的缺陷:
available_again = 0
for i in range(0,15):
time = 0.1*i
if time < available_again:
print("failed to schedule at " + str(time))
available_again = time + 0.1
此代码输出以下内容:
failed to schedule at 1.3
我没想到会出现这个错误,但我确实理解为什么会这样。我有什么选择才能解决这个问题?
我的代码中有一个修复:
available_again = 0.1*(i+1)
我想知道这是否是正确的路线。我的特定应用涉及事件的调度,其中事件发生的时间由复杂的数学函数决定,例如:sinc(2 * pi * f * t)。事件的持续时间会使事件彼此重叠,在这种情况下,我需要在不同的频道上发送它们。
答案 0 :(得分:1)
我的代码中有一个修复:
available_again = 0.1 *(i + 1)
此修复是正确的,只要time
保持足够小,浮点分辨率优于0.1(最多约2 50 ),您的代码就会正常工作。
这是有效的,因为在迭代0.1*(i+1)
计算的浮点数i
与用0.1*i
计算的浮点数完全相同 { {1}}在下一次迭代中增加了1,并且因为只要整数i
和n
保持低于约2 50 ,就没有两个{{1}对于m
和0.1*n
的不同值,{}和0.1*m
相等。
原因是浮点运算是确定性的。浮点运算n
可能会为m
的某些整数值产生反直觉结果,但它始终会为同一0.1 * n
生成相同的结果。
另外,如果n
是最接近的数学商i / 10,那么您应该将n
计算为time
,并在逻辑上计算time
1}}为i / 10.0
。
由于与上述相同的原因,它继续工作,并且它总是有额外的属性来计算最接近预期商的浮点数,而available_again
放大了浮点数之间的表示错误(i+1) / 10.0
和理性的1/10。
在两种情况下,0.1 * i
的两个连续值始终以相同的间隔分隔。使用0.1
计算,浮点值浮动在理性i / 10周围。使用time
,它将漂浮在i * 0.1000000000000000055511151231257827021181583404541015625周围。如果您可以自由选择采样频率,请选择它以使i/10.0
和0.1*i
之间的系数为2的幂(例如1/64或1/128)。然后,您将拥有精确计算i
的附加属性,并且每个时间间隔都完全相同。