Java中的浮点精度和相等性

知道浮点数,即使十进制格式小数点后的固定位数,也无法准确表示。 所以我有以下程序来测试:

public class Main { public static void main(String[] args) { System.out.printf("0.1 in single precision is %.50f\n", 0.1f); System.out.printf("0.2 in single precision is %.50f\n", 0.2f); System.out.printf("0.3 in single precision is %.50f\n", 0.3f); System.out.printf("0.1 + 0.2 in single precision is %.50f\n", 0.1f + 0.2f); System.out.printf("0.1 + 0.2 == 0.3 is %b in single precision\n", 0.1123f * 0.4f + 0.2f * 0.5f == 0.2f * 0.7f + 0.0123f * 0.4f); System.out.println(); System.out.printf("0.1 in double precision is %.50f\n", 0.1); System.out.printf("0.2 in double precision is %.50f\n", 0.2); System.out.printf("0.3 in double precision is %.50f\n", 0.3); System.out.printf("0.1 + 0.2 in double precision is %.50f\n", 0.1 + 0.2); System.out.printf("0.1 + 0.2 == 0.3 is %b in double precision\n", 0.1 + 0.2 == 0.3); } } 

输出如下:

 0.1 in single precision is 0.10000000149011612000000000000000000000000000000000 0.2 in single precision is 0.20000000298023224000000000000000000000000000000000 0.3 in single precision is 0.30000001192092896000000000000000000000000000000000 0.1 + 0.2 in single precision is 0.30000001192092896000000000000000000000000000000000 0.1 + 0.2 == 0.3 is true in single precision 0.1 in double precision is 0.10000000000000000000000000000000000000000000000000 0.2 in double precision is 0.20000000000000000000000000000000000000000000000000 0.3 in double precision is 0.30000000000000000000000000000000000000000000000000 0.1 + 0.2 in double precision is 0.30000000000000004000000000000000000000000000000000 0.1 + 0.2 == 0.3 is false in double precision 

我无法从上述结果中回答两个问题,我正在寻求帮助:

  1. 为什么0.20.3的双重表示看起来很精确,而0.1 + 0.2则不然。
  2. 为什么0.1f + 0.2f == 0.3f返回true?

  1. 我怀疑System.out.printf在这里正常工作。 获得写入0.1时获得的精确double精度值的可靠方法是编写new BigDecimal(0.1).toString()
  2. “为什么0.1f + 0.2f == 0.3f返回true?” 几乎是因为你很幸运:将0.1舍入到最接近的浮点表示,将0.2舍入到最接近的浮点表示并添加它们,使得最接近的可表示浮点数达到0.3。 总的来说这并不正确,这些价值恰好恰好起作用。