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()
比较浮点数(在任何语言中)通常都不是一个好主意。你可以减去它们,看看结果是否小于或等于某个非常小的数字。请参阅@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(经过多次跳跃)。偷偷隐藏,但它是指定的。