繁体   English   中英

文字与计算的浮点精度

[英]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.10.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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM