[读书笔记][Effective Java]不要在精确计算中使用float和double类型

来源:互联网 发布:利用淘宝客漏洞赚钱 编辑:程序博客网 时间:2024/03/28 19:44

在精确计算,尤其是有关金钱的商业运算中,不能使用floatdouble类型。

 

看如下的例子:

商店里某种糖果的价格是0.1元,0.2元,0.3元, …… 依此类推,一直到1.00元。现在你手中有1元钱。你想买一些糖果,假设你从1角的糖果开始依次买,一种价格的买一颗。计算一下一共可以买多少颗糖果,最后会剩下多少零钱。

 

第一个程序:

package com.mytest;

public class Test {
 private static final double FUNDS = 1.00;
 private static final double TEN_CENTS = .1;
 
    public static void main( String[] args ) {
     int itemsBought = 0;
     double myfund = FUNDS;
     for (double price = TEN_CENTS; price < myfund; price+= TEN_CENTS) {
   itemsBought++;
   myfund-= price;
  }
     
     System.out.println("itemsBought: " + itemsBought);
     System.out.println("myfund left: " + myfund);
    }
}

在这里,使用double类型,进行计算,但是却得到如下结果:

itemsBought: 3
myfund left: 0.3999999999999999

这并不是正确的结果。在涉及金钱的运算中,应该使用BigDecimal。

正确的程序如下:

package com.mytest;

import java.math.BigDecimal;

public class Test {
 private static final BigDecimal FUNDS = new BigDecimal("1.00");
 private static final BigDecimal TEN_CENTS = new BigDecimal(".10");
 
    public static void main( String[] args ) {
     int itemsBought = 0;
     BigDecimal myfund = FUNDS;
     for (BigDecimal price = TEN_CENTS; price.compareTo(myfund) <= 0; price = price.add(TEN_CENTS)) {
   itemsBought++;
   myfund = myfund.subtract(price);
  }
     
     System.out.println("itemsBought: " + itemsBought);
     System.out.println("change: " + myfund);
    }
}

打印结果:

itemsBought: 4
change: 0.00

这才是正确的答案。

In summary, don't use float or double for any calculations that require an exact answer.  User BigDecimal if you want the system to keep track of the decimal point and you don't mind the inconveneice of not using a primitive type.  Using BigDecimal has the added advantage that it gives you full controll over rounding, letting you select from eight rounding modes whenever an operation that entails rounding is performed.  This comes in handy if you're performing business calculations with legally mandated rounding behaviour.  If performance is of the essence, if you don't mind keeping track of the decimal point yourself, and if the quantities aren't too big, use int or long.  If the quantitiest don't exceed nine decimal digits, you can use int; if they don't exceed eighteen digits, you can use long.  If the quantities exceed eighting digits, you must use BigDecimal.

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 qq怎么办?q币转给微信 q币送不了别人怎么办 新qq号忘记了怎么办 手机qq登不上去怎么办 qq的账号忘了怎么办 微信红包密码输错锁了怎么办 陌陌钱包异常钱怎么办 对公账户转错了怎么办 微信零钱转账限额怎么办 微信红包充错话费怎么办 qq支付20万限额怎么办 qq红包20万限额怎么办 微信充qb冲错了怎么办 液相色谱柱干了怎么办 微信钱包充流量没到账怎么办 qq买流量不到账怎么办 冲q币电话冲错号了怎么办 下载cf什么文件损坏怎么办 cf老是36_2怎么办啊 永辉超市积分卡怎么办 超市积分卡丢了怎么办 医保卡磁条坏了怎么办 社保卡磁条坏了怎么办 鞋子长了怎么办m.s.cn 厚底皮拖鞋穿松了怎么办 白色帆布鞋洗后发黄怎么办 运动鞋子买大了怎么办 格力空调出现fo怎么办 绝味鸭脖代金券的附券撕了怎么办 耐克鞋子开胶了怎么办 苹果6s自动重启怎么办 钱不够想买手机怎么办 安卓机屏幕密码忘了怎么办 屏幕解锁密码忘了怎么办 华为手机屏幕解锁密码忘了怎么办 oppo锁屏密码忘了怎么办 云助理密码忘了怎么办 购买方发票丢了怎么办 普票发票联丢失怎么办 唯品金融没还款怎么办 金点原子锁打不开了怎么办