使用float可以使最大的“相对”水平是多少?


13

就像在《地牢围攻》和KSP等游戏中所演示的那样,由于浮点的工作原理,足够大的级别将开始出现故障。您不能在不损失精度的情况下将1e-20添加到1e20。

如果选择限制关卡的大小,如何计算对象开始变得不稳时可以移动的最低速度?

Answers:


26

32位浮点型有23位尾数

这意味着每个号码被表示为1.xxx XXX XXX XXX XXX XXX XXX XX一些功率的2,其中每个X是一个二进制数字,0或1(配极小非规格化数的例外小于倍2126 -它们以0开头,而不是1。但是接下来我将忽略它们)

因此,在2i2(i+1)的范围内,您可以表示精度为± 2 i 24 )的任何数字。±2(i24)

i=0(20)1=1(20)(1+223)1+224224

In this range:                You get accuracy within:
-----------------------------------------------
         0.25   -     0.5    2^-26 = 1.490 116 119 384 77 E-08
         0.5    -     1      2^-25 = 2.980 232 238 769 53 E-08
         1     -      2      2^-24 = 5.960 464 477 539 06 E-08
         2     -      4      2^-23 = 1.192 092 895 507 81 E-07
         4     -      8      2^-22 = 2.384 185 791 015 62 E-07
         8     -     16      2^-21 = 4.768 371 582 031 25 E-07
        16     -     32      2^-20 = 9.536 743 164 062 5  E-07
        32     -     64      2^-19 = 1.907 348 632 812 5  E-06
        64     -    128      2^-18 = 0.000 003 814 697 265 625
       128    -     256      2^-17 = 0.000 007 629 394 531 25
       256    -     512      2^-16 = 0.000 015 258 789 062 5
       512    -   1 024      2^-15 = 0.000 030 517 578 125
     1 024    -   2 048      2^-14 = 0.000 061 035 156 25
     2 048    -   4 096      2^-13 = 0.000 122 070 312 5
     4 096    -   8 192      2^-12 = 0.000 244 140 625
     8 192   -   16 384      2^-11 = 0.000 488 281 25
    16 384   -   32 768      2^-10 = 0.000 976 562 5
    32 768   -   65 536      2^-9  = 0.001 953 125
    65 536   -  131 072      2^-8  = 0.003 906 25
   131 072   -  262 144      2^-7  = 0.007 812 5
   262 144   -  524 288      2^-6  = 0.015 625
   524 288 -  1 048 576      2^-5  = 0.031 25
 1 048 576 -  2 097 152      2^-4  = 0.062 5
 2 097 152 -  4 194 304      2^-3  = 0.125
 4 194 304 -  8 388 608      2^-2  = 0.25
 8 388 608 - 16 777 216      2^-1  = 0.5
16 777 216 - 33 554 432      2^0   = 1

因此,如果您的单位为米,您将失去16 484-32 768波段(距原点约16-33公里)的毫米精度。

通常认为您可以通过使用其他基本单位来解决此问题,但这不是真的,因为相对精确度很重要。

  • 如果使用厘米为单位,则会在1 048 576-2 097 152波段(距原点10-21公里)处失去毫米精度。

  • 如果我们以公厘为单位,则会在128-256波段(距原点13-26公里)处失去毫米精度

...因此将单位更改为四个数量级仍然会导致数十公里范围内的毫米精度损失。我们要转移的只是它击中该频段的确切位置(由于base-10编号与base-2编号之间的不匹配)不会大幅扩展我们的可玩区域。

您的游戏所能容忍的不准确程度取决于您的游戏玩法,物理模拟,实体大小/绘制距离,渲染分辨率等细节,因此设置精确的临界值非常棘手。可能是您的渲染看起来与原点相距50公里,但子弹正在穿过墙壁传送,或者敏感的游戏脚本变得混乱。或者,您可能会发现游戏进行得很好,但是由于摄影机转换的不准确,一切都几乎无法察觉。

如果您知道所需的精度水平(例如,0.01个单位的跨度在您的典型查看/互动距离处映射为大约1 px,并且看不到任何较小的偏移量),则可以使用上表查找丢失的位置精度,并在有损操作的情况下将安全性降低几个数量级。

但是,如果您根本就在考虑远距离,最好通过在玩家移动时重新定义您的世界来回避所有这些。在原点周围选择一个保守的小正方形或立方体形区域。每当玩家移动到该区域之外时,请将其以及世界上的所有内容平移该区域一半的宽度,从而将玩家保持在内部。由于一切都一起进行,因此您的播放器不会发生变化。误差仍然可能发生在世界的偏远地区,但是与在脚下发生的误差相比,误差通常不那么明显,并且可以保证始终在播放器附近提供高精度。


1
绝对是必经之路!
弗洛里斯2014年

2
使用定点坐标怎么办?如有必要,也许使用64位整数?
API-Beast

问题是,重新居中的区域可以有多大?例如,如果在我的游戏中我想以高倍变焦进行远距离拍摄,我是否绝对需要使用双倍或足够浮动?根据四叉树或某种平铺算法,对更新者更好吗?
2014年

这将取决于渲染和物理系统采用的算法的数值稳定性-因此,对于给定的代码库/引擎,唯一确定的方法是尝试测试场景。我们可以使用该表来估计最大精度(例如,距离物体16公里的摄像机往往会看到至少毫米级的误差,因此,如果需要缩放,则您的缩放应足够宽,以使误差小于像素。 (如果您的游戏更加严格,则可能会加倍,或者可能需要一些聪明的数学运算),但是在此假设限制之前,一系列有损操作可能会遇到问题。
DMGregory

我仍然想知道,重新发布图形API的世界意味着什么。如果我有大量实例化(或非实例化)几何,这样做仍然安全吗?我想这意味着翻译所有转换,但是如果我多次执行,是否存在浮点精度损失的风险?
jokoon

3

这很难回答,因为它取决于你的物理规模:什么是可接受的最小移动速度,需要进行四舍五入,以零?

如果您需要广阔的世界和一致的物理学,最好使用定点类。

例如,在世界任何地方射击炮弹都会为您带来相同的结果,而64位固定点(32.32)则为您提供了巨大的精度,这比大多数游戏中所能感知的要多。如果您的单位是1米,那么您离原始点的距离仍为232皮秒,精度为2147483km。

您仍然可以在本地单元中的浮点中进行本地物理操作,以节省编程工作并使用现成的物理引擎。对于所有实际目的,它仍将合理地保持一致。

作为奖励,由于FPU延迟,宽相和AABB在定点趋于更快。将固定点转换为八叉树(或四叉树)索引的速度也更快,因为您可以执行简单的位掩码。

这些操作不能从通常会隐藏FPU延迟的SIMD指令和流水线中受益。

您可以将位置转换为浮点,然后再减去相机在固定点的位置以渲染所有内容,避免在大型环境中出现浮点问题,并且仍使用使用浮点的常规渲染器。


-3

您可以通过乘法完全避免它。
不用浮点数,只需将它们乘以10 ^(x),存储它们,然后在需要时再乘以10 ^(-x)。
由此,它取决于您要使用哪种int类型。


2
这不能避免问题。定点格式仍然具有有限的精度和范围-范围越大,精度越低(基于放置该固定小数点的位置)-因此决定“我可以在没有可见舍入错误的情况下制作一个水平”仍然适用。
DMGregory

3
而且,以10为底不是很实用。当您按对整数进行拆分时,定点数会更好地工作(考虑无符号26.6-小数部分是较低的6位(1.0 / 64.0 * x&63),而整数部分只是x >> 6) 。这比将某些东西提高到10的幂要容易得多。
安东·科尔曼
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.