Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/391.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中的浮点精度与等式_Java_Floating Point - Fatal编程技术网

Java中的浮点精度与等式

Java中的浮点精度与等式,java,floating-point,Java,Floating Point,众所周知,浮点数,即使是十进制格式中小数点后有固定数字的浮点数,也不能精确表示。因此,我要测试以下程序: 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);

众所周知,浮点数,即使是十进制格式中小数点后有固定数字的浮点数,也不能精确表示。因此,我要测试以下程序:

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
以上结果中有两个问题我无法回答,我正在寻求帮助:

  • 为什么
    0.1
    0.2
    0.3
    的双重表示看起来准确,而
    0.1+0.2
    却不准确
  • 为什么
    0.1f+0.2f==0.3f
    返回true
  • 我怀疑这里的
    系统.out.printf
    工作正常。要获得写入0.1时获得的准确的
    double
    值,可靠的方法是写入
    新的BigDecimal(0.1).toString()
  • “为什么0.1f+0.2f==0.3f会返回真值?”这几乎是因为你很幸运:将0.1四舍五入到最接近的浮点表示法,将0.2四舍五入到最接近的浮点表示法,然后将它们相加,你会得到最接近的可表示浮点到0.3。一般来说,情况并非如此,这些价值观只是碰巧起作用

  • 比较浮点数(在任何语言中)通常都不是一个好主意。你可以减去它们,看看结果是否小于或等于某个非常小的数字。请参阅@JFPicard的副本和可能的副本。这似乎不是副本;OP似乎意识到了这个问题,并试图更深入地理解它。我还怀疑0.1f+0.2f==0.3f返回true是巧合。但是,0.1+0.2==0.3返回false。我无法解释为什么单身是“走运”,但在这种情况下,双倍不是。也许是因为在这种情况下,双精度的额外有效数字与之相反?是的,差不多。更多的数字意味着很难幸运不同的舍入结果匹配。0.1000的printf输出。。。因为double大小写是正确的,至少在它与double.toString(0.1)一致的情况下是正确的。它在17位有效数字后显示零的原因是,toString在解析十进制将明确返回到原始双数的点处削减了输出。是的,它将输出字符串四舍五入,但这被定义为正确的,请参阅Double.toString的javadoc了解一些信息。@Durandal这是正确的,因为它反映了
    Double.toString
    ,但我相信OP的目标是提取由0.1表示的
    Double
    的真实数值。同意,这可能是他的想法。但这并不是判断正确性的合理依据。正确性需要根据某种规格来判断,而不是根据某人的意图或直觉。虽然定义非常迂回,但如果您遵循为printf提供的javadoc参考,您将到达Double.toString(经过多次跳跃)。偷偷隐藏,但它是指定的。