Java 当您需要使用浮点时,如何实际避免浮点错误?

Java 当您需要使用浮点时,如何实际避免浮点错误?,java,floating-point,precision,floating-accuracy,floating-point-precision,Java,Floating Point,Precision,Floating Accuracy,Floating Point Precision,我试图使用一些UI按钮将位置移动0.1或-0.1来影响3D模型的平移 我的模型位置是一个三维浮动,因此只需将0.1f添加到其中一个值,就会导致明显的舍入误差。虽然我可以使用BigDecimal之类的工具来保持精度,但我仍然必须将其从浮点转换为最终的浮点,结果总是会产生愚蠢的数字,使我的UI看起来一团糟 我可以对显示的值进行处理,但如果进行更多的编辑,舍入错误只会变得更严重,而且它们会使我的保存文件更难读取 那么,当我需要使用浮点时,如何避免这些错误呢?和算法有助于减少浮点错误 我会使用Ratio

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

我的模型位置是一个三维浮动,因此只需将0.1f添加到其中一个值,就会导致明显的舍入误差。虽然我可以使用BigDecimal之类的工具来保持精度,但我仍然必须将其从浮点转换为最终的浮点,结果总是会产生愚蠢的数字,使我的UI看起来一团糟

我可以对显示的值进行处理,但如果进行更多的编辑,舍入错误只会变得更严重,而且它们会使我的保存文件更难读取


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

和算法有助于减少浮点错误

我会使用
Rational
类。外面有很多,看起来应该行得通

Rational
被呈现为
float
时,一个显著的成本将是,当分母减少为
gcd
时,一个显著的成本将是。我发布的这个方法使分子和分母始终处于完全简化状态,如果你总是加减1/10,这应该是非常有效的

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

您应该选择最适合您的使用的实现。

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

四舍五入(2^n*值)*1/2^n

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

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

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

长数字链是二进制转换的人工制品, 实数的位数要少得多

因为浮点数是精确的,所以加法和减法都是精确的 不会引入偏移错误,但将始终是 只要位数是可预测的 不超过浮点值保持的时间

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

x=值*步长

当阶跃增加或减少1时,
将保留精度。

一个简单的解决方案是使用固定精度。i、 e.一个你想要的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位以上的精度,合理的舍入将不会看到这些错误。

加减。1f几次不会产生巨大的错误。最值得注意的是一次1的变化,就像期望的结果是4,但在转换为整数的过程中,生成的结果稍微少一些,并被截断为3。这将在转换前通过四舍五入进行修正。如果您遇到其他错误,则可能是其他错误。请显示示例数据和代码,说明您遇到的问题。最简单的方法:增加/减少0.125。问题报告使用浮点。更改为double将比Kahan求和算法提供更多的错误减少,并且更便宜(在大多数硬件上)。但是,这两种方法都无法解决通过截断将非常轻微错误的结果转换为整数时出现的错误。您的目的是什么?尽管这消除了加法和减法过程中的错误,但在某些范围内,它会增加总错误,因为使用的步长(.100006…)与所需的步长不同。这使得计算结果与期望结果不同。你是如何期望得到期望的结果的?因为如果计算的目标不关心它是0.1还是0.100,这通常并不重要。。。在这种特定情况下,三维模型会按特定数量增加或减少。我使用这个技巧,例如在积分间隔中,因为如果开始位置和增加间隔是一个精确的浮点,则相加速度更快、更精确。事实上,我建议使用0.125,因为这意味着在8个步骤中,我又得到了一个整数值,将1.0除以8个步骤并不是不自然的。这个答案无法解释它本身。其目的显然是更改步长,而不是修复最初建议的步长出现的错误,但问题陈述中不清楚更改的步长是否可以接受。显然,这改变了软件的行为:随着步长的改变,从3步到4步不再只有10步。也许这对询问者来说是可以接受的,也许不是。但答案当然应该介绍这一提议,并解释它正在改变观察到的行为,并解决其后果。