在java中操作和比较浮点

Pra*_*eth 10 java floating-point floating-accuracy

在Java中,没有精确表示浮点运算.例如这个java代码:

float a = 1.2; 
float b= 3.0;
float c = a * b; 
if(c == 3.6){
    System.out.println("c is 3.6");
} 
else {
    System.out.println("c is not 3.6");
} 
Run Code Online (Sandbox Code Playgroud)

打印"c不是3.6".

我对超过3位小数的精度感兴趣(#.###).我如何处理这个问题来乘以浮点数并可靠地比较它们?

bob*_*bah 19

它是浮点数不应该像进行比较的一般规则(A == B) ,而是喜欢(Math.abs(a-b) < delta)在那里三角洲是一个小数目.

具有十进制形式的固定位数的浮点值不必具有二进制形式的固定位数.

为清晰起见添加:

虽然严格的==浮点数的比较具有非常小的实际意义上说,严格的<>比较,相反,是一个有效的用例(实施例-当某些值超过阈值的逻辑触发:(val > threshold) && panic();)

  • 无论有什么例子,建议人们使用公差进行比较都存在一个基本的**问题.它会增加错误报告**的相等性,并且,因为您不知道该应用程序,您无法知道这是否可接受或是一个问题. (4认同)
  • "准确比较" - 是一个毫无意义的术语,它无法量化.我想我对IEEE754很了解,我给出的答案正是回答了这个主题的问题,它是紧凑而明确的.相反,你的评论是如此笼统,以至于它几乎是一个异端. (3认同)
  • 建议使用容差进行比较是不恰当的建议,因为它减少了不平等的错误报告,代价是增加了错误的平等报告,并且您无法知道这对您不了解的应用程序是否可接受.申请可能对寻求不平等"更感兴趣"而不是寻求平等,或者可能有其他需要满足的规范. (2认同)
  • @Eric - 当使用浮点数时,没有身份或不公平的概念,只有一个距离的概念.如果在公式中我给出了答案,你将`<`替换为`>`,你将得到一个标准来比较不等式的距离浮点数.对于大多数实际应用来说,浮点数在计算机存储器中的表示的逐位同一性是不感兴趣的 (2认同)

Dav*_*d M 7

如果您对固定精度数字感兴趣,您应该使用固定精度类型BigDecimal,而不是像固有的近似(虽然高精度)类型float.Stack Overflow上有许多类似的问题,可以通过多种语言更详细地介绍这些问题.


Dan*_*iar 5

我认为它与Java无关,它发生在任何IEEE 754浮点数上。这是因为浮点表示的性质。使用IEEE 754格式的任何语言都将遇到相同的问题。

正如上面David所建议的,您应该使用java.lang.Math类的abs方法来获取绝对值(除去正/负号)。

您可以阅读以下内容:http : //en.wikipedia.org/wiki/IEEE_754_revision,而且好的数字方法教科书也可以充分解决该问题。

public static void main(String[] args) {
    float a = 1.2f;
    float b = 3.0f;
    float c = a * b;
        final float PRECISION_LEVEL = 0.001f;
    if(Math.abs(c - 3.6f) < PRECISION_LEVEL) {
        System.out.println("c is 3.6");
    } else {
        System.out.println("c is not 3.6");
    }
}
Run Code Online (Sandbox Code Playgroud)