您的位置:首页 > 编程语言 > Java开发

java double类型运算问题

2016-04-13 14:12 190 查看
问题重现:

double i = 0.1;
System.out.println(i+i+i);


运行上面的语句,最终的结果是:



很奇怪,并不是想象中的0.3,错误在哪里?

原因:这其实是计算机内部机制导致的问题,具体就是计算机中存储浮点数的机制,导致浮点数如果参与了运算,那么就可能会丧失精度,产生预期之外的结果,当然这里只是可能,有以下运算确实会恰巧复合预期结果。

那么结论:即尽量不要用double或者float来进行精确运算,会丧失精度。double和float适合科学计算,bigdecimal才适合精确计算。构建bigdecimal用string的参数。所谓的科学计算就是会算出很长的小数,最后按需求取舍就可以了。比如天文学或者化学中的质量测定,都不需要特别精确,取小数点后多少多少位就可以了。但如果是经融或者医疗领域,那就必须精确,不能取舍。

计算机存储浮点数原理:

正数存储就是补码(取反加一)。

浮点数在IEEE中也有详细的表示方式。大致是最高位表示正负,中间的几位表示尾数,最后的几位表示指数。

具体过程,首先拿到一个十进制的小数,

1,先将其转换为二进制的小数,整数部分除二取余法,小数部分则是乘二取整法;

2,移位,使得小数点的左边只有一个1,然后记下移动了多少位,假设是n位,那么指数部分就是n的二进制表示,当然,n可正可负;

3,根据正负设置符号位

4,取小数点后面的尾数设置尾数位,因为移位后小数点前面只有一个1,所以这个1不用记录,只要记录小数部分即可;

5,记录指数部分;

这就是double或者float在底层的实现。

从上面的过程可以知道,在将一个十进制的小数的小数部分转换为二进制的小数时,除非最后的一位是5,否则是不可能乘尽的,也就意味着这个十进制的小数是无法用二进制来精确表示的,如果double参与了运算,那么结果肯定有很大的概率不是精确的。这就解释了开始的奇怪结果。要想精确计算最好采用bigdecimal。但是,如果double没有参与运算,直接打印,结果却没有任何问题,这个还没有深究过。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: