Libgdx可以在其坐标系中存储非常大的数字吗?

时间:2017-08-31 22:32:40

标签: java libgdx

我正在尝试用科学精确的太阳系编写游戏,并试图找出大规模使用坐标的最佳方法。当我读到Libgdx中的坐标系时,它说它使用“浮点”来存储坐标数据。

我希望厘米精度达到约55亿公里,即小数点后12位。我担心这个大的时候坐标不准确。

有人可以对此有所了解吗?

3 个答案:

答案 0 :(得分:2)

我从未使用libgdx库,但查看其API(例如Vector3或Rectangle),似乎它使用float s。

浮筒

Java float表示二进制科学记数法中的数字,即每个数字由23位有效数字和8位指数表示。把它想象成一个表格(就像你银行的转账表格,你必须写下你要转账的金额)。在每个框中,您可以撰写10float form

注意:23 + 8 = 31,丢失的位用作数字的符号。在这个答案中,我们不处理负数或负指数。

精密

由于指数的原因,对于较大的数字,浮点数的精确度会降低。一些例子:

 10_000_000 == 1E7 != 1E7 + 1 == 1.0000001E7 ==  10_000_001
100_000_000 == 1E8 == 1E8 + 1 == 1.0000000E8 == 100_000_000 

在10 8 时,有效数字不足以表示相差1。

让我们计算一下您的用例的精确度,其中数字不会超过55亿公里(以厘米为单位):

5.5×10 9 km = 5.5×10 14 cm = 1.11110100001110001101101 010100000011 bin ×2 48 cm

由于我们只有23位来表示该数字,因此它近似为

1.11110100001110001101101 bin ×2 48 cm = 549'999'989'489'664 cm
= 5'499'999'894'896.64 m = 5'499'999'894.896 64 km

你将离开超过100公里!

可能的解决方法

  • 使用另一个使用double而非float的库。双打有52位有效数字,对于您的用例来说足够精确。
  • 每个位置使用两个float:粗略位置和细粒度偏移(不推荐)。
  • 不要试图这么精确。我怀疑任何人都可以跟踪外太阳系中厘米级精确的物体。

答案 1 :(得分:1)

理想情况下,您希望创建使用BigDecimal的{​​{3}},因为您可以控制有效数字的数量。因此,BigDecimal表示的数字的值是(unscaledValue×10-scale),your own version of a Vector

答案 2 :(得分:1)

提出有趣的解决方案是一个很好的问题。

您的问题标记为libgdx,因此我的解决方案不会使用它。让我们来处理每个问题。

无关紧要,它仍然浮动

首先,我需要告诉你,无论你有多么精确的位置(浮点数,双数),libgdx的底层系统最后会跟float一起使用。查看其SpriteBatch类,其中使用float表示在屏幕上绘制内容时的位置,以及Sprite类,其中基于float的位置也取决于其位置。

这意味着无论您的精确度如何,都会在float屏幕上绘制内容。

精密

此外,无论您使用float还是double,都会遇到浮点计算错误。如果你不能一蹴而就(我根本不了解你的游戏要求),无论是关于你的游戏的位置还是别的什么,那么你可能需要考虑使用BigDecimal 。银行申请会使用这样的东西,因为四舍五入错误不会丢失任何一点,客户可能会抱怨!

您可以通过在游戏对象中维护BigDecimal来逃避。您可以通过它们更新其位置,而不是在libgdx中设置位置的正常方式。但是无论何时你需要绘制,你都可以通过doubleValue()获得它的价值。为什么加倍而不浮动?最好能够为游戏提供最高精度,因此当浮动数不能100%准确地表示数字时,您将获得尽可能少的错误。

BigDecimal很慢

小心,因为BigDecimal比正常的浮点运算慢。查看其基准herehere

的变通方法

因为我发现在某个时间点,用户只会在您的空间中看到有限的区域。或者即使您可能有一个允许用户缩小以查看整个区域的空间地图,那也是您不需要精确度或精确度double精确度的时间。 libgdx的默认方式就足够了,不需要切换游戏库(其他人大多数都会基于float)。

这仍然是您仍然可以使用float,但使用BigDecimal或仅String来表示屏幕上没有涉及的任何重大科学价值的原因在运行时影响游戏性能的计算。因此,我相信这可以让我们缩小距离,这样你就可以用相同的意图表示游戏对象,使其具有科学的正确性。