使用浮点数存储大量数字



我用floats来表示游戏中的位置:

struct Position
{
float x;
float y;
};

我想知道这是否是最佳选择,以及随着头寸价值的不断增长,后果会是什么。我花了一些时间复习一下浮标是如何存储的,并意识到我有点困惑。

(我正在使用Microsoft Visual C++编译器。

float.h中,FLT_MAX定义如下:

#define FLT_MAX         3.402823466e+38F        /* max value */

这是340282346600000000000000000000000000000.

该值远大于UINT_MAX定义为:

#define UINT_MAX        0xffffffff

并对应于值4294967295

基于此,似乎float存储非常大的数字(如仓位)是一个不错的选择。尽管FLT_MAX非常大,但我想知道精度问题将如何发挥作用。

根据我的理解,一个float用 1 位来存储符号,8 位来存储指数,用 23 位来存储尾数(假设前导为 1):

S EEEEEEEE MMMMMMMMMMMMMMMMMMMMMMM

这意味着FLT_MAX可能如下所示:

0 11111111 11111111111111111111111

这相当于:

1.11111111111111111111111 x 2^128

111111111111111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

即使知道这一点,我也很难想象精度的损失,并且随着值的不断增加,我感到困惑。

有没有更简单的方法来思考这个问题?floatsdoubles通常用于在unsigned int之类的东西上存储非常大的数字吗?

考虑浮点精度的一种方法是考虑它们具有大约 5 位精度。因此,如果你的单位是米,而你有1公里外的东西,那就是1000米 - 试图以10厘米(0.1米)或更小的分辨率处理该物体可能会有问题。

游戏中的常用方法是使用浮点数,但要划分世界,使位置相对于局部坐标系(例如,将世界划分为一个网格,并且每个网格正方形都有一个平移值)。一切都将具有足够的精度,直到它相对于相机进行渲染转换,此时远处事物的不精确性不是问题。

举个例子,想象一个以太阳系为背景的游戏。如果坐标系的原点位于太阳的中心,那么行星表面的坐标将无法在浮标中准确表示。但是,如果你有一个相对于行星表面的坐标系,而这个坐标系又是相对于行星的中心,然后你知道行星相对于太阳的位置,你可以精确地对局部空间中的事物进行操作,然后转换为你想要渲染的任何空间。

不,他们不是。

假设自游戏对象移动以来,您的位置需要为某个帧增加 10 厘米。

假设游戏世界以米为单位缩放,则为 0.10。但是,如果您的float值足够大,它将无法再表示 0.10 的差异,并且您增加该值的尝试将失败。

您是否需要存储大于 16.7m 的值和小数部分? 那么浮点数就会太小。

布鲁斯·道森(Bruce Dawson)的这个系列可能会有所帮助。

如果您确实需要处理非常大的数字,请考虑使用任意精度的算术库。您必须分析代码,因为这些库比内置类型的算术慢。

您可能实际上并不需要非常大的坐标值。例如,您可以环绕世界的边缘,并使用模算术来处理位置。

最新更新