因为我的案例与游戏项目有关,所以我考虑在GameDev上发布这个问题,但我认为这更适合更广泛的编程 SE。请让我知道这个问题是否会更好地发布在那里。
根据我的理解——如果我错了,请纠正我——移动游戏开发(这是我的情况)可以从使用定点计算中受益匪浅,因为这将确保平台之间的更多一致性,并且会提高性能设备无法正确处理浮点的情况。
但是定点确实有局限性,最明显的是溢出。所以我的问题是,假设我们已经确定定点是给定目标平台的最佳选择,如何确定给定项目的要求是否允许使用它们。
为了让事情更清楚,我想分享一些我遇到问题的代码:
CIwVec2 calculateBezier(float t, CIwVec2 p0, CIwVec2 p1, CIwVec2 p2) {
float u = 1 - t;
CIwVec2 p = IW_FIXED(u * u) * p0; // (1 - t)²P0
p += IW_FIXED(2 * u * t) * p1; // 2(1 - t)tP1
p += IW_FIXED(t * t) * p2; // t²P2
return p;
}
在这个项目中,我使用Marmalade SDK,它使用 C++ 并带有自己的定点数实现(它们有 16 位和 32 位,我现在使用的是 32 位)和一个 Vector 类(CIwVec2) 使用该实现进行位置和计算(包括标量乘法,如上面的代码所示)。哦,IW_FIXED 只是一个将浮点数转换为定点数的宏。
当我尝试运行上述代码时,出现乘法溢出错误。调试值如下:
t = 0
u = 1 (which converts to 4096 in int32 fixed-point with IW_FIXED)
p0.x = 1638400 (400.0f with IW_FIXED_TO_FLOAT)
p0.y = 409600 (100.0f with IW_FIXED_TO_FLOAT)
老实说,我对定点数没有完全的了解。我理解这个想法,但是定点运算对我来说并不完全清楚(我一定已经放弃了大多数与基数 2 相关的数学课,真让我感到羞耻)。但是我完全被这样一个事实所震惊,像 1.0f * 400.0f 这样简单的东西会导致定点溢出。
所以,虽然我认为在我的项目中支持定点不会有问题,但似乎情况并非如此。该游戏是一个自上而下的汽车游戏,不会有巨大的轨道或任何东西,但它们必须至少与设备的屏幕一样大(或者更好的是,它的分辨率),因为我们的目标是对于平板电脑来说,像 1.0f * 400.0f 这样的问题意味着定点是不可能的。
我对这个假设是否正确?而且,对于未来的项目和其他有类似问题的人,我们如何评估项目中定点数的可行性?此外,如何在 16 位和 32 位之间做出决定将是一个很大的好处:)
(对不起,很长的帖子,感谢您的时间!)
更新:
所以,总结一下到目前为止的一些反应。理想的情况是以某种方式实现您的定点数,以便具有满足您需求的必要范围(Mooing Duck 的回答)。此外,对于 32 位数字的操作,最安全的做法是使用 64 位进行计算(timday 的答案和 Max 的评论)。顺便说一句,Marmalade 确实有一些“安全的固定乘法”函数,但对于 CIwVec2 的标量乘法运算符重载(它IW_FIXED_MUL
在下面使用,它不能安全地乘法),情况并非如此。
最后,关于我的特定场景,似乎从 Marmalade 6.1 开始,仅使用浮点数可能是最好的解决方案。
编辑: 虽然 Max 的回答确实解决了我的问题,但这主要是因为它是果酱特有的东西。正因为如此,我选择了 Mooing Duck 的答案作为选择的答案,因为我觉得它通常会帮助更多的人。