第48条:如果需要精确的答案,请避免使用float和double
2017-12-04 14:30
399 查看
float和double主要为了科学计算和工程计算而设计,执行二进制浮点运算,这是为了在广泛的数值范围上提供较为精确的快速近似计算而精心设计的。然而,它们没有提供完全精确的结果,所以不适合用于需要精确结果的场合,尤其是货币计算。
使用舍入可以解决上面问题,但并不是所有的问题都能用舍入解决,如有1元,有0.1,0.2,0.3,一直到1元的糖果,从0.1开始买,直到不能支付为止:
结果是:
使用BigDecimal是正确的办法:
结果是:
使用BigDecimal的缺点是:1.与基本类型相比,不方便(需要创建BigDecimal对象);2.速度慢
使用int或者long,取决于涉及的数值大小,同时要自己处理十进制小数,以分为单位,而不是以元为单位计算,就可以使用int来处理:
结果与用BigDecimal是一样的。
总结:对于需要精确答案的计算,不能使用float或者double,BigDecimal允许完全控制舍入,如果业务要求涉及多种舍入方式,使用BigDecimal很方便,如果性能很关键,涉及的数值不大,就可以使用int或者float,如果数值范围没有超过9位十进制数字,可以使用int,如果不超过18位数字,使用long,如果数值可能超过18位,就必须用BigDecimal。
//假设有1.03元,花掉0.42元后 System.out.println(1.03 - .42);//0.6100000000000001 System.out.println(1.00 - 9 * .10);//0.09999999999999998
使用舍入可以解决上面问题,但并不是所有的问题都能用舍入解决,如有1元,有0.1,0.2,0.3,一直到1元的糖果,从0.1开始买,直到不能支付为止:
public static void main(String[] args) { double funds = 1.00; int itemsBought = 0; for(double price = .10; funds >= price; price += .10) { funds -= price; itemsBought++; } System.out.println(itemsBought + " items bought."); System.out.println("Money left over: $" + funds); }
结果是:
使用BigDecimal是正确的办法:
public static void main(String[] args) { final BigDecimal TEN_CENTS = new BigDecimal(".10"); int itemsBought = 0; BigDecimal funds = new BigDecimal("1.00"); for(BigDecimal price = TEN_CENTS; funds.compareTo(price) >= 0; price = price.add(TEN_CENTS)) { itemsBought++; funds = funds.subtract(price); } System.out.println(itemsBought + " items bought."); System.out.println("Money left over: $" + funds); }
结果是:
使用BigDecimal的缺点是:1.与基本类型相比,不方便(需要创建BigDecimal对象);2.速度慢
使用int或者long,取决于涉及的数值大小,同时要自己处理十进制小数,以分为单位,而不是以元为单位计算,就可以使用int来处理:
public static void main(String[] args) { int itemsBought = 0; int funds = 100; for(int price = 10; funds >= price; price += 10) { itemsBought++; funds -= price; } System.out.println(itemsBought + " items bought."); System.out.println("Money left over: $" + funds); }
结果与用BigDecimal是一样的。
总结:对于需要精确答案的计算,不能使用float或者double,BigDecimal允许完全控制舍入,如果业务要求涉及多种舍入方式,使用BigDecimal很方便,如果性能很关键,涉及的数值不大,就可以使用int或者float,如果数值范围没有超过9位十进制数字,可以使用int,如果不超过18位数字,使用long,如果数值可能超过18位,就必须用BigDecimal。
相关文章推荐
- Java:Effective Java 学习笔记(第48条:如果需要精确的答案,请避免使用float和double)
- 第48条:如果需要精确的答案,请避免使用float和double
- 如果需要精确答案,请避免使用float和double
- 第四十八条:如果需要精确的答案,请避免使用float和double
- 《effective java》48—如果需要精确的答案,请避免使用float和double
- 需要精确答案,避免使用float和double
- 如果要求精确的答案,请避免使用float和double
- 如果要求精确的答案,请避免使用float和double
- 31-如果要求精确的答案,请避免使用float和double
- Effective Java(2nd Edition) Item 48 如果需要精确结果,请避免使用float与double(译文)
- 表达式之谜2找零时刻(需要精确答案的地方,避免使用float和double;货币运算使用int,long或BigDecimal)
- Effective Java读书笔记--如果想要知道精确的答案,就要避免使用double和float
- 如果要求精确的答案,请避免使用float和double
- 精确运算避免使用float和double
- 天天记录 - Java 精确计算避免使用float和double
- 精确运算避免使用float和double
- Java中需要精确计算的,不要用float, double, 请用BigDecimal
- [读书笔记][Effective Java]不要在精确计算中使用float和double类型
- 不要在精确计算中使用float和double类型