当前位置: 代码迷 >> J2SE >> Java 精度有关问题 求详解
  详细解决方案

Java 精度有关问题 求详解

热度:142   发布时间:2016-04-23 20:22:29.0
Java 精度问题 求详解
System.out.println(0.2+0.4);//想想为什么不是0.6
System.out.println(0.6);//为什么又是0.6
------解决方案--------------------
java采用的是二进制系统,整数没问题,但是在小数的二进制运算并不一定是精确的。就像十进制无法精确表示1/3一样,二进制却无法精确表示1/10,这就是java浮点运算不一定得到精确值的原因。所以如果浮点运算想要精确值的话,就用BigDecimal类。
------解决方案--------------------
嗯这是个相当有水平问题,浮点数(double和float)可能不能精确表示小数,这句话是对的,但应该和这个问题没有本质关系

Java的默认小数数值类型是double,double固然是不能精确表示0.6的,但是如果你println一个double,只会打印出它的有效数位,对于double来说就是17位,0.6用double来表示是0x3FE3333333333333,再转换回小数是0.5999999999999999777955395074......,根据浮点数舍入规则,截取17位有效数字以后就是0.6000000000000000。
所以如果你println(0.6),结果就是0.6,后面的0自动省略了。

但是如果你println(0.2 + 0.4),这个在编译的时候,编译器就会进行0.2 + 0.4这个加法运算(Java编译优化的问题,这个不多讲,反正这个加法一般不是在运行期进行的,而是编译的时候就运算好了的,当然就算是在运行期进行的运算也会是相同的结果),这个加法就是问题所在,虽然你知道结果是0.6,虽然double类型的0.6打印出来就是0.6,但这个加法的结果却不是0.6,System.out.println(0.2 + 0.4 == 0.6),你会发现打印的是false,浮点数之间的运算不能保证精确度,这应该才是本质问题。
浮点数0.2与0.4的和其实是0x3FE3333333333334,转换成小数是0.60000000000000008881784197......,舍入以后就变成0.6000000000000001了。