如何处理浮点舍入错误

Sin*_*ion 2 java floating-point precision floating-accuracy

我正在尝试用Java实现游戏的基本2D矢量数学函数.它们将被游戏密集使用,所以我希望它们尽可能快.

我开始用整数作为矢量坐标,因为游戏对坐标不需要更精确,但是对于所有计算,我仍然需要改变为双向量以获得清晰的结果(例如,两条线之间的交点).

使用双打,有舍入错误.我可以简单地忽略它们并使用类似的东西

d1 - d2 <=  0.0001
Run Code Online (Sandbox Code Playgroud)

比较值,但我假设进一步的计算误差可以总结,直到它变得重要.所以我认为我可以在每次可能不精确的操作之后绕过它们,但结果却产生了更糟糕的结果,因为该程序还会舍入不正确的值(例如0.33333333...- > 0.3333300...).

使用BigDecimal会太慢.

解决这个问题的最佳方法是什么?

Eva*_*tol 5

不准确的方法

当您使用需要精确计算的数字时,您需要确保您没有做类似的事情:(这就是您目前正在做的事情)

错误积累

随着过程的继续,这将导致舍入错误的累积; 长期为您提供极为无懈可击的数据.在上面的例子中,你实际上是四舍五入开始float 4次,每次它变得越来越不准确的!


准确的方法

一个更好,更准确地获取数字是要做到这一点: 避免累积错误

这将有助于避免累积误差的累积,因为每次计算仅基于1次转换,并且该转换的结果不会复合到下一次计算中.

最好的攻击方法是以必要的最高精度开始,然后根据需要进行转换,但保持原始状态不变.我建议你按照我发布的第二张照片的流程进行操作.

我开始用整数作为矢量坐标,因为游戏对坐标不需要更精确,但是对于所有计算,我仍然需要改变为双向量以获得清晰的结果(例如,两条线之间的交点).

重要的是要注意,如果对最终结果没有明显影响,则不应尝试对值进行任何类型的舍入; 如果做得足够频繁的话,你只会做很少甚至没有收获的工作,甚至可能会降低性能.