我正在尝试使用一些 UI 按钮来影响 3D 模型的翻译,以将位置移动 0.1 或 -0.1。
我的模型位置是一个三维浮点数,所以简单地将 0.1f 添加到其中一个值会导致明显的舍入误差。虽然我可以使用 BigDecimal 之类的东西来保持精度,但我仍然必须将它从浮点数转换为最后的浮点数,它总是会导致愚蠢的数字,让我的 UI 看起来像一团糟。
我可以只显示显示的值,但舍入错误只会随着更多的编辑而变得更糟,它们使我的保存文件很难阅读。
那么当我需要使用浮点数时,如何真正避免这些错误呢?
我正在尝试使用一些 UI 按钮来影响 3D 模型的翻译,以将位置移动 0.1 或 -0.1。
我的模型位置是一个三维浮点数,所以简单地将 0.1f 添加到其中一个值会导致明显的舍入误差。虽然我可以使用 BigDecimal 之类的东西来保持精度,但我仍然必须将它从浮点数转换为最后的浮点数,它总是会导致愚蠢的数字,让我的 UI 看起来像一团糟。
我可以只显示显示的值,但舍入错误只会随着更多的编辑而变得更糟,它们使我的保存文件很难阅读。
那么当我需要使用浮点数时,如何真正避免这些错误呢?
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 位以上的精度,并且通过合理的舍入将不会看到这些错误。
如果您坚持使用浮点数:避免错误的最简单方法是使用精确但接近所需值的浮点数
圆形(2^n * 值)* 1/2^n。
n 是位数,值要使用的数字(在您的情况下为 0.1)
在您的情况下,精度越来越高:
n = 4 => 0.125
n = 8(字节)=> 0.9765625
n = 16(短)=> 0.100006103516 ....
长数链是二进制转换的产物,实数的位数少得多。
由于浮点数是精确的,因此加法和减法不会引入偏移误差,但只要位数不超过浮点值所保持的长度,就始终是可预测的。
如果您担心使用此解决方案会影响您的显示(因为它们是奇数浮点数),请仅使用和存储整数(步长增加 -1/1)。内部设置的最终值是
x = 值 * 步长。
随着步长增加或减少 1,精度将保持不变。