Xia*_*Cuo 11 c++ floating-point epsilon game-engine
在书中游戏引擎架构:"......,假设我们使用浮点变量来跟踪绝对游戏时间,以秒为单位.在我们的时钟变量幅度变得如此之大以至于增加1/30之前我们可以运行我们的游戏多长时间一秒钟它不再改变它的价值?答案是大约12.9天." 为什么12.9天,如何计算呢?
当浮点计算的结果无法准确表示时,它会四舍五入到最接近的值.因此,您希望找到最小值x,使得增量f = 1/30小于x与下一个最大浮点数之间的宽度h的一半,这意味着x + f将回绕到x.
由于同一个binade中的所有元素的间隙相同,我们知道x必须是其binade中的最小元素,这是2的幂.
因此,如果x = 2 k,那么h = 2 k-23,因为浮点数具有24位有效数.因此,我们需要找到最小的整数ķ这样
2 k-23 /2> 1/30
这意味着k > 19.09,因此k = 20,并且x = 2 20 = 1048576(秒).
请注意,x /(60×60×24)= 12.14(天),这比您的答案提议的要少一点,但凭经验检查:在朱莉娅
julia> x = 2f0^20
1.048576f6
julia> f = 1f0/30f0
0.033333335f0
julia> x+f == x
true
julia> p = prevfloat(x)
1.04857594f6
julia> p+f == p
false
Run Code Online (Sandbox Code Playgroud)
更新:好的,那么12.9来自哪里?12.14是游戏时间,而不是实际时间:由于浮点中涉及的舍入误差(特别是在结束时,当舍入误差实际上相对于f非常大时),这些将会发散.据我所知,没有办法直接计算,但实际上迭代32位浮点数相当快.
再次,在朱莉娅:
julia> function timestuff(f)
t = 0
x = 0f0
while true
t += 1
xp = x
x += f
if x == xp
return (t,x)
end
end
end
timestuff (generic function with 1 method)
julia> t,x = timestuff(1f0/30f0)
(24986956,1.048576f6)
Run Code Online (Sandbox Code Playgroud)
x匹配我们之前计算的结果,t是30秒钟的时钟时间.转换为日期:
julia> t/(30*60*60*24)
9.640029320987654
Run Code Online (Sandbox Code Playgroud)
甚至更远.所以我不知道12.9来自哪里......
更新2:我的猜测是12.9来自计算
y = 4× f /ε= 1118481.125(秒)
其中ε是标准机器epsilon(1和下一个最大浮点数之间的差距).将此缩放到天数为12.945.这提供了x的上限,但如上所述,它不是正确的答案.