浏览 4151 次
锁定老帖子 主题:浮点数运算的陷阱
精华帖 (0) :: 良好帖 (0) :: 新手帖 (2) :: 隐藏帖 (4)
|
|
---|---|
作者 | 正文 |
发表时间:2010-04-03
/** * @author crane.ding */ public class Test { public static void main(String[] args) { final float ff = 0.6f + 0.1f; final double fd = 0.6f + 0.1d; final double df = 0.6d + 0.1f; final double dd = 0.6d + 0.1d; System.out.println(ff + " : " +(ff == 0.7f)); System.out.println(fd + " : " +(fd == 0.7d)); System.out.println(df + " : " +(df == 0.7d)); System.out.println(dd + " : " +(dd == 0.7d)); System.out.println("\nfloat"); for (float f = 0; f < 1; f = f + 0.1f) System.out.println(f); System.out.println("\ndouble"); for (double d = 0; d < 1; d = d + 0.1) System.out.println(d); } } 运行结果如下: 0.70000005 : false 0.7000000238418579 : false 0.7000000014901161 : false 0.7 : true float 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.70000005 0.8000001 0.9000001 double 0.0 0.1 0.2 0.30000000000000004 0.4 0.5 0.6 0.7 0.7999999999999999 0.8999999999999999 0.9999999999999999 从以上的运行结果我们不难看出,浮点数的运算是有误差的,例如0.2加0.1就不等于0.3;对于金额的运行如果采用浮点数,那计算出来的金额就不一定是准确的;这也是许多程序开发人员经常接触,而未考虑到的一个小陷阱。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2010-04-04
不是未考虑,用BigDecimal,而且这样的文章这里也有不少的.
|
|
返回顶楼 | |
发表时间:2010-04-04
呵呵! 是啊,昨天突然想到就在博客上做一下笔记记下来! BigDecimal的目的就是精确的表示小数,但是其开销也是挺大的。BigDecimal对象是不可变的,每一次操作都会产生新的BigDecimal对象,显然BigDecimal不太适合大量的数据运算。
|
|
返回顶楼 | |
发表时间:2010-04-06
那最好的方式应该怎么处理呢!
|
|
返回顶楼 | |
发表时间:2010-04-08
如果能确保一些前提的话,用double也是可行的。
至少应该确认数字的精度要求在一定数量内、总位数在一定数量内。 这时候所谓的陷阱根本不是问题,完全可以用其他方式搞定。 比较时用差数小于一定值。比如人民币用0.001。 再比如说数据库指定长度而不是傻乎乎的Number/Decimal,输出加format等等。 但保证累计误差问题就麻烦了,呵呵,碰上来回加减的就知道厉害了。 比如说一系列成本按比例拆分到若干部门/业务,有些钱数很大,累计拆下来累计误差可能就够收支对不齐了。 在财务眼里这属于对他们的屠杀兼IT自杀。 再举个例子,对人民币可以用0.001以内当相等。 但有带三位小数的钱,比如说突尼斯。得改成四位小数判等。 又有钱超级不值钱数额很大的,考虑钱数上线的时候可能要按10以内算相等。 虽然说用BigDecimal类似问题也偶尔需要考虑,但总归少多了。 如果用double,等修改钱数范围的时候就知道想撞墙是什么意思了。 大家都知道,能在变更的时候把这么细节的修改涉及的所有地方都想到的是超人。 所以没明确证据表明确实是BigDecimal影响性能到不可用、且其他修改更困难之前,还是用BigDecimal吧。 |
|
返回顶楼 | |