[英]Floating point precision in literals vs calculations
我想知道为什么Java中的浮点数在初始化为文字时可以表示精确值,但是当它们表示某些计算结果时它们是近似值。 例如:
double num1 = 0.3;
double num2 = 0.1 + 0.2;
System.out.println(num1);
System.out.println(num2);
为什么结果是:
0.3
0.30000000000000004
并不是:
0.30000000000000004
0.30000000000000004
当没有精确的二进制表示0.3。 我知道BigDecimal类,但我不太明白这个原始数字的不一致性。
这三个数字中没有一个可以完全表示为double
。 您得到不同结果的原因是,添加0.1
到0.2
之后的值具有与0.3
不同的表示误差。 大约5.5E-17的差异足以在打印出结果( 演示 )时产生差异。
double a = 0.2;
double b = 0.1;
double c = 0.3;
double d = a+b;
double e = d-c; // This is 5.551115123125783E-17
当0.3被转换为其表示为1和0然后转换回小数时,它将舍入为0.3。 但是,当0.1和0.2分别转换为二进制时,误差在加法时相加,以便在总和转换回十进制时显示。 详尽的解释将涉及演示每个数字的IEEE表示以及添加和转换。 有点涉及,但我希望你有这个想法。
添加本身不能产生0.3
的精确表示,因此打印0.1 + 0.2
的结果产生0.30000000000000004
。
另一方面,当调用System.out.println(0.3);
, println(double)
方法将对结果执行一些舍入:它最终调用Double.toString(double)
,它提到结果是近似的:
m或a的小数部分必须打印多少位? 必须至少有一个数字来表示小数部分,并且除此之外必须有多个,但只需要多少,更多的数字来唯一地区分参数值和double类型的相邻值。 也就是说,假设x是由该方法为有限非零参数d生成的十进制表示所表示的精确数学值。 那么d必须是最接近x的double值; 或者如果两个double值同样接近x,则d必须是其中之一,d的有效位的最低有效位必须为0。
如果你使用BigDecimal
,可以看到差异:
System.out.println(0.3); // 0.3
System.out.println(new BigDecimal(0.3)); // 0.299999999999999988897769753748434595763683319091796875
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.