我已经考虑过将这个问题发布在 加梅德夫 由于我的案例涉及到一个游戏项目,但我认为这将更适合更广泛的编程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;
}

在这个项目中,我正在使用 果酱SDK, ,它使用C++并带有他们自己的定点数字实现(它们有16位和32位,我现在使用32位),以及一个向量类(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)

说实话,我对定点数字没有完全的了解。我理解这个想法,但定点操作对我来说并不完全清楚(我必须放弃与base2相关的大多数数学课程,对我感到羞耻)。但我完全被这样一个事实所困扰,即像1.0f*400.0f这样简单的东西会导致定点溢出。

所以,虽然我认为在我的项目中支持定点不会有问题,但看起来可能并非如此。这款游戏是一款自上而下的汽车游戏,它不会有很大的轨道或任何东西,但它们必须至少和设备的屏幕一样大(或者更好的是,它的分辨率)。

我对这个假设是正确的吗?而且,对于未来的项目和其他有类似问题的人,我们如何评估项目中定点数字的可行性?此外,如何在16位和32位之间做出决定将是一个很好的奖励:)

(对不起,很长的帖子,感谢您的时间!)

更新资料:

所以,总结一下到目前为止的反应。理想的情况是实现你的定点数字,以便有必要的范围为您的需要(Mooing鸭子的anwer)。此外,对于具有32位数字的操作,最安全的做法是使用64位(timday的答案和Max的评论)进行计算。顺便说一句,Marmalade确实有一些"安全的固定乘法"函数,但对于ciwvec2的标量乘法运算符重载(它使用 IW_FIXED_MUL 下,其不mupliply安全地)。

最后,更多关于我的特定场景,似乎从Marmalade6.1开始,只使用浮动可能是最好的解决方案。

编辑: 虽然Max的答案确实解决了我的问题,但主要是因为它是橘子酱特有的东西。正因为如此,我选择了Mooing Duck的答案作为选择的答案,因为我觉得这个答案会帮助更多的人。

有帮助吗?

解决方案

定点可以被看作是存储一个分数的上半部分,而你的情况下的下半部分是4096。所以1.0f等于4096/4096,它作为4096存储在内存中。我不会进入分数乘法的细节,因为我不记得它们,但重要的部分是乘法时 A/D * B/D 得到一个结果 C/D, ,则 CA*B/D.

所以:你在哪里 1.0f * 400.0f, ,计算机将此视为 4096 * 1638400 / 4096.一点点代数表明这应该导致1638400(400.0f),但是如果分数点库不够聪明,那么在进行除法之前,它最终会得到一个临时值6710886400,这对于一个 int.

由于您的浮点分母为4096,因此您的"浮点数"精确到最接近的0.00024,并且范围为-524288.999f到524287.999f(ish)。你的编译器有没有办法降低"浮点数"的准确性以获得更多的范围?否则你就死定了。

编辑

Max确认4096是果酱的一部分,不能更改。在这种情况下,我看到很少有选择:
(1)不要使用定点。
(2)尽量保持所有浮点数在-128到128之间。
(3)使用一个特殊的函数乘以一个标量和一个 CIwVec2 这使用 IW_FIXED_MUL 下面。优选地,包 float 在一个特殊的类和重载 operator* 打电话 IW_FIXED_MUL.不提供隐式转换为 float, ,否则你永远不会找到所有的错误。

其他提示

你所看到的,它暗示的32位中间体(参见mooing duck的答案)似乎对我来说是一个严重的弱点。

我在过去成功使用了固定点libs(在386/486时代的x86上),它们都在纠正换档之前使用了64位中间的乘法(其实我似乎记得英特尔提供了非常好的32x32-到64位乘法指令,这是完美的)。较高的中间精度在数据范围内购买了很多自由;我真的讨厌与这种橘子披露的Lib似乎是限制的东西,但可以看出他们为什么他们可能不得不以便为流提原因而做。

当您使用Marmalade 6.1时,在移动开发中使用固定点并没有意义 Marmalade 6.1它在9月发布。

没有FPU的Android手机很少,但大多数手机都有FPU,GPU带Gles 1.0和Gles 2.0 我们现在用橘子酱瞄准Gles 2.0设备。

Marmalade有iw_fixed的原因是他们有自己的图形层,称为IWGX。

2012年9月之前(Marmalade 6.1)。IWGX不支持浮点。 这就是为什么即使在最近的Gles 2.0设备上,开发人员也被迫使用固定数字。

今天没有使用固定数量的果酱。

-

无论如何,如果您仍然希望多个固定点,有 iw_fixed_mul 功能

添加:代码在示例中是正确的。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top