日期:2014-05-20  浏览次数:20761 次

菜鸟提问:关于double类型变量取值精度问题
有个程序
Java code
public class Test {
    public static void main(String[] args) {
        double pi = 3.1415;
        double r = 6.5;
        double v = 2*pi*r;
        System.out.println(v);
}
}


当pi取值为3.1415的时候,结果为40.8395,但是当pi取值为3.14159的时候,结果变成了40.840669999999996,我想知道为什么结果的小数一下变成那么多位?谢谢大家了!

------解决方案--------------------
double在java中是4个字节,但4个字节也无法完全表示所有的double,看下计算机组成会更容易理解。
解决时使用BigDecimal运算成功后在转回来,或者Math.round的四舍五入。
------解决方案--------------------
计算机二进制数据无法精确表示十进制小数
2进制表示小数的时候只能够表示能够用1/(2^n)的和的任意组合

参考:
0.5能够表示,因为它可以表示成为1/2
0.75也能够表示,因为它可以表示成为1/2+1/(2^2)
0.875也能够表示,因为它可以表示成为1/2+1/(2^2)+1/(2^3)

但是0.1不能够精确表示,因为它补能够表示成为1/(2^n)的和的形式
------解决方案--------------------
我也不清楚啊!挺有意思啊!


自己猜想一下:

首先计算机无法表示连续的数,所以表示的数只能是离散的。 感觉double就是用 64 bit 表示 0101010010 位串,可能是作运算时,要先把 3.1415之类的数转化为 010100 之类的位串,之后做乘法,交给CPU 的ALU了,之后的到的 010101010 位串,再转化成 10进制的小数。

可能是3.1415的,和3.14159的 两种情况最后算出(运算中进位)的 位串从右向左 第一个 1 的位置比较靠前,所以转化的10进制 精度小些?导致最后精度不同。

求高人指点~




------解决方案--------------------
参考我的帖子http://topic.csdn.net/u/20111021/23/03e2362d-f133-4074-b8a0-234a70db750c.html
以及http://zh.wikipedia.org/wiki/IEEE_754
------解决方案--------------------
可以这么理解 在计算机中 所有的数字都是二进制的 而一个小数是无法在有限的位数内 转化为一个精确的二进制数来表示的 所以 就会出现lz的问题 类似2.0-1.1一样

这个是输出0.8999999999999999
public class jingdu{
public static void main(String[] args){
System.out.print(2.0-1.1);
}
}

由于小数是0.1 在化二进制的时候是个循环的 即使用double也是无法精确表示的
0.1*2=0.2
0.2*2=0.4
0.4*2=0.8
0.8*2=1.6
0.6*2=1.2
0.2*2= 0.4
........