如何在需要使用float时实际避免浮点错误?

我试图使用一些UI按钮来影响3D模型的转换,以将位置移动0.1或-0.1。

我的模型位置是一个三维浮点数,因此只需将0.1f添加到其中一个值就会导致明显的舍入误差。 虽然我可以使用像BigDecimal这样的东西来保持精度,但我仍然必须将它从浮点数转换回到最后的浮点数,它总是会导致愚蠢的数字使我的UI看起来像一团糟。

我可以很好地显示显示的值,但是舍入错误只会随着更多编辑而变得更糟,并且它们使我的保存文件难以阅读。

那么当我需要使用浮点数时,如何才能真正避免这些错误呢?

我会使用Rational类。 那里有很多 – 这个看起来应该有效。

一个重要的成本将是当Rational被渲染为float以及当分母被缩减为gcd 。 我发布的那个保持分子和分母始终处于完全缩小的状态,如果你总是增加或减去1/10,这应该是非常有效的。

此实现保持值标准化(即具有一致的符号)但未减少。

您应该选择最适合您使用的实施方案。

Kahan求和和成对求和算法有助于减少浮点误差。 这是Kahan算法的一些Java代码 。

一个简单的解决方案是使用固定精度。 即你想要的整数10倍或100倍。

 float f = 10; f += 0.1f; 

 int i = 100; i += 1; // use an many times as you like // use i / 10.0 as required. 

我不会在任何情况下使用float ,因为你得到更多的舍入误差而不是double的旁边没有任何好处(除非你有数百万的浮点值) double给你8个精度的数字并且明智的舍入将不会看到那些错误。

如果你坚持使用浮点数:避免错误的最简单方法是使用精确的浮点数,但接近所需的值,即

round(2 ^ n * value)* 1/2 ^ n。

n是位数,值是要使用的数字(在您的情况下为0.1)

在你的情况下,精度越来越高:

n = 4 => 0.125
n = 8(字节)=> 0.9765625
n = 16(短)=> 0.100006103516 ….

长数字链是二进制转换的假象,实数具有更少的比特。

由于浮点数是精确的,加法和减法不会引入偏移误差,但只要位数不长于浮点值,就会始终可预测。

如果您担心使用此解决方案会损害您的显示器(因为它们是奇数浮点数),请仅使用和存储整数(步长增加-1/1)。 内部设置的最终值是

x =值*步。

当步长增加或减少1时,将保持精度。