关于浮点精度以及为什么仍要使用它


38

在大世界中,浮点数一直是精度问题。

文章解释了背后的幕后,并提供明显的选择-定点数。一些事实确实令人印象深刻,例如:

“高达64位的精度使您可以达到亚微米级精度的冥王星距太阳最远的距离(74亿公里)。”

亚微米精度远胜过任何fps所需的精度(对于位置甚至速度),这将使您能够构建真正的广阔世界。

我的问题是,如果定点具有这样的优势,为什么还要使用浮点数呢?大多数渲染API和物理库都使用浮点数(并且存在浮点数的缺点,因此开发人员需要绕开它们)。

他们这么慢吗?

另外,您如何看待可扩展的行星发动机(例如:outerera或infinity)能够大规模处理?他们使用固定点作为位置还是有一些空间划分算法?


3
最后一个“附加”的位可能应该是一个单独的问题,这样主要的位不会被忽略。
Tetrad

我想弄清楚如何强制定点...我的游戏有各种各样奇怪的错误,因为Lua也使用FPU,DirectX也用FPU摆弄...我已经看到2 * 9000 = 17995或500 * 10 = 4897真的很傻。但最坏的错误可能是一个被在OGRE3D论坛讨论的,其中,1 + 5 = 4
调速装置

3
没有理由发表评论;但是如果您决定使用定点Q浮点数(en.wikipedia.org/wiki/Q_(number_format))是您的朋友;它们非常快速且易于实现。
乔纳森·迪金森

因此,总结一下?我应该坚持使用浮点数(如果我使用Java或Python)?-加斯顿26分钟前
加斯顿

Answers:


20

如果您愿意允许我使用无耻的插件,我将为您提供我正在开发真实游戏的示例(YouTube视频链接)。

游戏在物理引擎上具有一个无限的,程序生成的世界。它使用单精度浮点数。在几百米的游戏空间之后,精度问题开始出现(并且随着距离的增加,精度问题会越来越严重)。

我的解决方案?我每隔200m左右就将整个世界向原点移动200m(如果您想在我的站点上找到并尝试其中的一个原型,并打开[w] orld调试覆盖图,则可以看到这种情况)。

为什么不使用定点?还是双精度?而不是单精度?因为其他一切都使用单精度浮点!

我使用的物理引擎使用它,XNA使用它,将加载到图形卡上的数据格式化为单精度浮点。甚至语言本身也设计为可以使用浮点数-书写和(更重要的是)阅读0.5f比容易得多0x80000000L

这只是在实践中更简单的问题。显而易见的赢家是意识到浮点精度问题,并编写了相当简单的“将世界移回零”功能(或实现空间分区或任何适合您的游戏的功能)。

最后是另一个例子-Orbiter是真正需要考虑精度的游戏(实际上是模拟)。不仅在太空而且在时间上(时间加速加上绕行的物体-现在都不希望它们从天上掉下来)。它还使用浮点数,并使用hack来保持稳定性。


我一直想知道某些应用程序是否可以更轻松地移动其他所有内容并将“玩家”保留在原点。有趣的是,我不是唯一的一个!
dash-tom-bang 2010年

我喜欢你的推理。我只想指出,涉及网络定点的游戏似乎具有较少的怪癖/偏差(客户端预测更准确)。
乔纳森·迪金森

我不太了解你的论点。顺便说一句,为什么语言还没有实现定点?当然,这似乎是吸引使用浮点数的原因,但这并不能解释为什么没有在所有地方都实现定点。
18

@jokoon我认为我的答案很明确。至于为什么没有到处都实现定点?只需看一下Wikipedia:“很少有计算机语言包含对定点值的内置支持,因为对于大多数应用程序而言,二进制或十进制浮点表示法通常更易于使用且足够准确。” 优秀的设计师知道该忽略什么,并且以某种方式复制功能的方式可以使程序员真正轻松地射击自己,这是一个不错的选择。
安德鲁·罗素

同意 当今的处理器非常容易执行浮点指令,这些指令具有出色的吞吐量,并且大多数指令的延迟都比整数指令长几个周期。
doug65536

11

首先-是的,它们明显更快。即使您可以使固定点的工作速度与“常规” FPU一样快,真实的浮点也具有有利的指令,例如fsel可以停止分支,或者SIMD可以一次在多个浮点上工作。GPU至少在面向用户的界面中还使用浮点。

其次,64位也会使您浮点数增加很多-大多数人仍然使用32位,但是主要优点是它可以扩展。该定点标度具有固定的精度。无论您是测量到冥王星的太阳还是在街对面,都可以得到相同的精度。当涉及的所有值都较小时,浮点数将为您提供更准确的结果。由于一般物理学库至少可以与许多不同比例的游戏兼容,并且某些游戏本身的比例可能大不相同,因此它们需要使用一种可以在许多比例上运行的数字。


5

另一个重要的一点是,浮标并不像这里的人们所认为的那样准确。32位浮点型具有24位全整数精度。这意味着对于任何给定范围,它至少与24位定点值一样准确。尽管浮点数的准确性变得越差,但其值变得越大,则定点值将简单地溢出并在某个点处回绕。降低精度是更好的后备。浮标也可能溢出,但是很久以后。我想看到您的脸,当您的世界由于定点溢出而突然转至-2 ^ 31时。

64位浮点值具有53位整数精度,因此它们确实非常准确。


浮点值实际上并不会溢出。如果计算结果的大小太大而无法表示,则结果为正或负无穷大。
菠萝

3

在FPS上下文中,定点值实际上可能是一种负债。接近零的浮点数更准确。仅在较大距离上,定点才更可取。答案很简单,就是它取决于上下文。

在类似银河系的事物中,您可以使用参考系。对太阳系使用大比例尺,然后将太阳的中心(或类似点)用作系统内部任何物体的起点。使用这个系统,您可以吃蛋糕,也可以吃,这并不难想象。

IIRC的Infinity开发人员表示,他在一次采访中一直在围绕规模问题进行迭代。


在任何游戏中都不太可能需要浮点数的“接近零”精度。如果您的单位是一米,则10位精度可以使您获得亚毫米级的精度,并且如果您坚持使用32位值,则仍可以在每个方向上进行4000公里以上的建模。如果需要比毫米更高的精度,那么可以肯定地再移位几位。在太空游戏中移至64位值将使您在整个体积中具有恒定精度的太阳系(或更多?)。
dash-tom-bang 2010年

确实。这就是为什么在星系大小的世界中将太阳系的太阳用作参考点的原因!关键是,您选择的处理精度的方法不会对表产生任何影响。这没有什么意义,因此您不妨使用您的库/硬件调整到的一种。
Rushyo 2010年

顺便说一句,我从事的游戏必须在每个方向上进行超过4000公里的建模。为了与其他项目中的代码兼容,它必须使用32位作为位置。考虑到对代码重用的商业需求以及当今游戏世界的规模,这不是一个理论问题。

1

如果您还没有,请务必在GameDev.net上查看Planet Rendering教程。对于空间划分,一种解决方案是保留两个单独的位置变量-一个宏观尺度和一个微观尺度。效果很好(经过测试)。

确切的解决方案取决于您打算如何处理发动机中的极限距离-您计划跳闸还是时间压缩?


1

原因之一是浮点算法“足够好”(或至少已经足够),它可以快速产生相当准确的结果。

只要您知道浮点算法的局限性,并更改算法以应对它们(请参阅Andrew Russell的答案),您就会生成“有效”的代码。


-1

我在写游戏。在我的游戏/程序中,我使用相当固定的相机在原点绘制一艘太空船,而我的行星则使用单独的相机绘制。这两件事对我来说很重要,但是我的星球还不够详细。至于安德鲁·罗素(Andrew Russell)提到的有关移动世界的解决方案(并且我假设照相机及其居民返回原点),如果您打算将游戏制作成网络游戏,我真的不会尝试。如果您根据每个客户端的移动在服务器应用程序上移动世界,那么最终世界将为一个职位而苦苦挣扎。所有人都将一直扮演自己的角色,这将是一个巨大的故障。

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.