2

我正在编写一个带有浮点数的示例程序,但突然发生了一些奇怪的事情。如果有人能阐明为什么我会在我的程序中面临这种行为,我将不胜感激。

package Programs;

public class FloatTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        float f1 = (float) 3.2;
        float f2 = (float) 6.5;
        if (f1 == 3.2) {
            System.out.println(f1 + " same");
        } else {
            System.out.println(f1 + " different");
        }
        if (f2 == 6.5) {
            System.out.println(f2 + " same");
        } else {
            System.out.println(f2 + " different");
        }
    }
}

输出:

3.2 different
6.5 same

在做了一些改变 f2 值的测试后,我注意到我得到了 f2 > 3.5 的意外结果,这是为什么?任何输入都非常感谢。

谢谢

4

6 回答 6

5

我将尝试对此进行技术解释。由于这些值最终以二进制格式存储,因此在某些情况下会丢失精度。

6.5不应丢失任何精度,因为它可以转换为二进制值110.1

3.2但是,不能像这样干净地转换,因为 的二进制表示.2变得不合理。这将是类似的东西11.00110011..。这充其量只能在以3.2另一种方式转换时四舍五入。

如果有人可以验证我在说什么,那就太棒了——这是基于对 Java 如何处理这个问题的公认有限知识。

于 2013-09-13T19:15:50.737 回答
3

由于浮点变量的表示方式,并非所有数字都可以精确表示。事实上,很少有人能做到。

当你写

float f1 = (float) 3.2;

并将其与 3.2 进行比较,您将f1(a float) 与3.2(a double:3.2作为文字输入的隐含double类型) 进行比较。在您的 statement 中f1 == 3.2f1被隐式转换为 a double,但到那时,精度已经丢失。这是因为3.2是那些无法精确表示的数字之一,double并且比float.

巧合的是,由于 Java 用于表示浮点的内部方案,可以精确表示6.5的数字(double或)之一。float这就是为什么,在你的情况下,f2 == 6.5true

于 2013-09-13T19:13:20.670 回答
2

有很多方法可以解决这个问题,

出现此问题的原因是十进制值无法在二进制文件中准确表示。

  1. 有一个公差值并检查差异是否小于公差值。
  2. 将其乘以 10/100/...,然后比较数字
  3. 查看BigDecimal

一定要经历这个。

于 2013-09-13T19:10:16.407 回答
2

:) Ahh IEEE754 和 JVM 与浮点数的区别。简而言之,6.5 与浮点值 6.5 不同。6.5 == 6.5f 会起作用,但你更好地理解你在做什么!请阅读http://en.wikipedia.org/wiki/IEEE_floating_point,还请注意用于跨平台强制 IEEE754 行为的“strictfp”关键字。这里有很多事情要考虑,舍入行为、优先顺序、JVM 差异等。不是整数或长整数的事情出乎意料地棘手。

您正在处理数字的二进制表示,该数字的精度适用于不需要无限精确答案的许多类型的数学计算。对于许多工程和金融系统,尤其是那些涉及乘法或分数的系统,这是不可接受的。您要么需要重新计算您的会计基础(使用理解金钱和小数的金融类),(例如用便士计算金钱),并且对于工程,您可能需要使用 BigDecimal 或具有特定舍入行为、精度等的相关类.

再举一个例子,浮点值 1/3 + 1/3 + 1/3,可能等于也可能不等于 1。因为构成数据的数字表示的 1 和 0 并不是精确的 1/3。在我的特定平台(JVM 1.6 Windows 64 位)上,它是 1.0,但它可能不在你的平台上。

于 2013-09-13T19:10:56.970 回答
2

使用演员if (f1 == (float)3.2) {然后它会工作。

像这样的文字3.2是 double 类型,并且您正在将 float 与 double 进行比较,它会导致此类事情发生。

正如@JNL 指出的

出现此问题的原因是十进制值无法在二进制文件中准确表示。

于 2013-09-13T19:17:31.063 回答
1

虽然它可能看起来不正确,但当你运行时

float f1 = (float) 3.2;

f1并不等于 3.2。如前所述,有几种方法可以解决此问题。

于 2013-09-13T19:16:04.960 回答