在《 Game Engine Architecture》一书中:“...,假设我们使用浮点变量来跟踪绝对游戏时间(以秒为单位)。在时钟变量的大小变大以至于增加1/30之前,我们可以运行游戏多长时间一秒钟它不再改变其值(value)了吗?答案大约是12.9天。”
为什么要12.9天,如何计算呢?

最佳答案

如果无法精确表示浮点计算的结果,则将其舍入到最接近的值。因此,您希望找到最小值x,以使增量f = 1/30小于x与下一个最大浮点之间的宽度h的一半,这意味着x + f将四舍五入为x。

由于间隙对于相同binade中的所有元素都是相同的,我们知道x必须是其Binade中的最小元素,即2的幂。

因此,如果x = 2k,则h = 2k-23,因为float具有24位有效数。所以我们需要找到最小的整数k

2k-23/2> 1/30

这意味着k> 19.09,因此k = 20,x = 220 = 1048576(秒)。

请注意,x/(60×60×24)= 12.14(天),比您的答案提出的要少,但是凭经验进行了检验:在Julia中

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

更新:好的,那么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)
x与我们之前计算的结果匹配,并且t是30秒的时钟时间。转换为天数:
julia> t/(30*60*60*24)
9.640029320987654

甚至更远。所以我不知道12.9的来源...

更新2:我的猜测是12.9来自计算

y = 4×f/ε= 1118481.125(秒)

其中ε是标准machine epsilon(1与下一个最大浮点数之间的距离)。将其缩放到几天就可以得到12.945。这提供了x的上限,但这不是如上所述的正确答案。

09-10 03:50
查看更多