在Java中比较浮点数

5

可能重复:
Java中操作和比较浮点数

我在Java中比较浮点数时应该使用Epsilon吗? Float.compare(float f1, float f2)静态方法是否安全可用?

谢谢!

编辑:我想我明白了。

当我在eclipse中写入,比如说,3.6f,编译器将这个数字解释为3.6。然而,当我写1.2f * 3.0f时,结果是3.6000001。虽然从数学上讲这是错误的,但这两个结果显然是不相等的。因此,在检查相等性时需要有一个Epsilon。

然而,当我在eclipse中写入0.0f时,编译器将其解释为0严格地说,因为IEEE 754能够正确处理它。因此,确保一个浮点数严格为正(value > 0.0f)是正确的。

我唯一看到的问题是当计算机不使用IEEE 754表示时,而是使用一个不能正确处理0的表示。

我是对的吗?


1
答案取决于您要做什么。实际上,是否应该使用浮点数也取决于它。先解释一下手头的问题,然后才能得到有用的答案。 - Matti Virkkunen
以什么方式安全?这是一个方便的方法,可以处理一些边缘情况,但它不能防止你或我创建自己的错误。此外,在尝试为浮点数实现自己的equals方法时,我使用了epsilon,但在比较它们时没有使用。 - Hovercraft Full Of Eels
抱歉没有说明得够清楚。我正在为一个游戏编写粒子。我想知道当deltaTime(浮点数)等于0.0时,因为我使用速度=距离*(1 / deltaTime)计算速度。拥有无限速度有点傻。现在我使用(Float.compare(deltaTime,0.0f)!= 0)来确保deltaTime大于0.0。deltaTime不能小于0。 - Klems
如果结果等于10^-20,那你的情况有多糟糕?如果是10^-30呢?你还认为唯一需要关注的是负时间吗? - duffymo
我指的是时间不可能为负数。这完全不可能。我想知道当 deltaTime 严格大于 0 时,以及 Float.compare 看起来可以解决这个问题。如果我只想知道 float 是否严格为正,我可以使用 (deltaTime > 0.0) 对吗? - Klems
2个回答

14

Math.ulp()方法在测试中有实际用途。正如您无疑所知,通常不应该将浮点数进行精确比较,而是检查它们是否相等且误差在一定的容限范围内。例如,在JUnit中,您可以像这样比较期望值和实际浮点数值:

assertEquals(expectedValue, actualValue, 0.02);

这个断言表明实际值与期望值之间的误差在0.02以内。但是0.02是否是一个合理的容限呢?如果期望值是10.5或-107.82,那么0.02可能非常合适。然而,如果期望值是几十亿,那么0.02可能与零完全相同。通常,您应该根据ULP(单位最后位)的相对误差来进行测试。根据计算需要的精度,通常在1到10 ULP之间选择容忍度。例如,在这里我指定实际结果需要与真实值相差5 ULP:

assertEquals(expectedValue, actualValue, 5*Math.ulp(expectedValue));

http://www.ibm.com/developerworks/java/library/j-math2/index.html


1
如果一个值很大,而另一个值很小,那该怎么办?取和的ULP是否是个好主意? - Winter

4

是的,建议使用公差来检查两个浮点数之间的绝对值差异。

比较可以告诉您一个双精度浮点数是否小于、等于或大于另一个。它不会告诉您它们彼此之间有多接近,因此,比使用 == 进行比较更安全。


如果你不喜欢我的编辑,请撤销它;+1。 - aioobe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接