kalman03

          每天早上看一遍《福布斯》富翁排行榜,如果上面沒(méi)有我的名字,我就去學(xué)習(xí)......
          隨筆 - 22, 文章 - 0, 評(píng)論 - 86, 引用 - 0
          數(shù)據(jù)加載中……

          Java中浮點(diǎn)數(shù)的精度問(wèn)題

          當(dāng)您在計(jì)算Money的時(shí)候,請(qǐng)看好了?。。∫粨p失了別后悔?。。?/span>

          現(xiàn)象1

              public static void main(String[] args) {

                 System.out.println(0.030*100);//輸出3.0

                 System.out.println(0.031*100);//輸出3.1

                 System.out.println(0.032*100);//輸出3.2

                 System.out.println(0.033*100);//輸出3.3000000000000003

                 System.out.println(0.034*100);//輸出3.4000000000000004

                 System.out.println(0.035*100);//輸出3.5000000000000004

                 System.out.println(0.036*100);//輸出3.5999999999999996

                 System.out.println(0.037*100);//輸出3.6999999999999997

                 System.out.println(0.038*100);//輸出3.8

                 System.out.println(0.039*100);//輸出3.9

              }

          現(xiàn)象2

              public static void main(String[] args) {

                 BigDecimal b1 = new BigDecimal("0.236");

                 BigDecimal b2 = new BigDecimal(0.236);

                 System.out.println(b1);//輸出0.236

                 System.out.println(b2);//輸出0.2359999999999999875655021241982467472553253173828125

          }

          描述:

          當(dāng)我們使用一些“特殊的數(shù)字”進(jìn)行運(yùn)算時(shí),或者調(diào)用BigDecimalnew BigDecimal(double val)進(jìn)行構(gòu)造的時(shí)候,將得到意想不到的結(jié)果。

          原因:

          Java中,浮點(diǎn)類型是依據(jù)IEEE754標(biāo)準(zhǔn)的。IEEE754定義了32位和64位雙精度兩種浮點(diǎn)二進(jìn)制小數(shù)標(biāo)準(zhǔn)。采用二進(jìn)制表示double,float等浮點(diǎn)數(shù)是不準(zhǔn)確的。

          同時(shí)BigDecimalAPI聲明,建議使用new BigDecimal(String val)進(jìn)行構(gòu)造,使用new BigDecimal(double val)進(jìn)行構(gòu)造的時(shí)候,將得到意想不到的結(jié)果(The results of this constructor can be somewhat unpredictable)。

          解決辦法(以0.236*100 = 23.599999999999998為例)

          1、 通過(guò)String結(jié)合BigDecimal來(lái)轉(zhuǎn)換。

                 String val = "0.236";

                 //使用new BigDecimal(String val)進(jìn)行構(gòu)造

                 BigDecimal a = new BigDecimal(""+val);

                 BigDecimal b = new BigDecimal(""+100);

                 //小數(shù)的位數(shù)與構(gòu)造參數(shù)的位數(shù)一致

                 System.out.println(a.multiply(b));//輸出23.600

          2、  通過(guò)移位結(jié)合BigDecimal來(lái)轉(zhuǎn)換

                 String val = "0.236";

                 //使用new BigDecimal(String val)進(jìn)行構(gòu)造

                 BigDecimal a = new BigDecimal(""+val);

                 //向右移兩位

                 a = a.movePointRight(2);

                 System.out.println(a);//輸出23.6

          3、  使用保留小數(shù)位的方法來(lái)轉(zhuǎn)換

                 double result = 0.236*100;

                 System.out.println(result);//輸出23.599999999999998

                 //計(jì)算保留result小數(shù)點(diǎn)后四位,以此類推,1后面幾個(gè)零就是保留小數(shù)點(diǎn)后幾位數(shù).如下保留兩位小數(shù)

                 result = (double)(Math.round(result*100)/100.0) ;

                 System.out.println(result);//輸出23.6

          4、 使用DecimalFormat來(lái)確定小數(shù)點(diǎn)后位數(shù)

                 double val = 0.236*100;

                 //保留小數(shù)點(diǎn)后兩位,若保留三位為"#.000"

                 DecimalFormat df = new DecimalFormat("#.00");

                 String str = df.format(val);

                 System.out.println(Double.valueOf(str));//輸出23.6

          5、-----方法很多,一個(gè)即可

          心得:

          處理這樣的精度問(wèn)題方法很多,只要不是直接采用浮點(diǎn)數(shù)進(jìn)行計(jì)算就行。

          附加:

          IEEE 754用科學(xué)記數(shù)法以底數(shù)為2的小數(shù)來(lái)表示浮點(diǎn)數(shù)。32位浮點(diǎn)數(shù)用1位表示數(shù)字的符號(hào),用8位來(lái)表示指數(shù),用23位來(lái)表示尾數(shù),即小數(shù)部分。作為有符號(hào)整數(shù)的指數(shù)可以有正負(fù)之分。小數(shù)部分用二進(jìn)制(底數(shù)2)小數(shù)來(lái)表示。對(duì)于64位雙精度浮點(diǎn)數(shù),用1位表示數(shù)字的符號(hào),用11位表示指數(shù),52位表示尾數(shù)。如下兩個(gè)圖來(lái)表示:

          float(32):

          1位,符號(hào)位

          冪(8位)

          尾數(shù)(32位)

          double(64):

          1位,符號(hào)位

          冪(11位)

          尾數(shù)(52位)

          都是分為三個(gè)部分:

          (1)一個(gè)單獨(dú)的符號(hào)位s直接編碼符號(hào)s。

          (2)k位的冪指數(shù)E,移碼表示

          (3)n位的小數(shù),原碼表示。

          posted on 2010-10-25 21:10 kalman03 閱讀(4024) 評(píng)論(1)  編輯  收藏 所屬分類: J2EE

          評(píng)論

          # re: Java中浮點(diǎn)數(shù)的精度問(wèn)題  回復(fù)  更多評(píng)論   

          這。。。。。。

          凡是有點(diǎn)常識(shí)的人都知道,浮點(diǎn)型不能直接用來(lái)運(yùn)算。。

          通常都是用大數(shù)型來(lái)進(jìn)行運(yùn)算的。。。
          2010-11-08 10:31 | 指尖流沙

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 滨海县| 南平市| 清涧县| 墨玉县| 绍兴县| 永德县| 平原县| 江门市| 阳江市| 铅山县| 恩施市| 五河县| 安达市| 五家渠市| 朝阳市| 商洛市| 汝城县| 交口县| 兴仁县| 信丰县| 广安市| 宜君县| 江山市| 莱西市| 黄大仙区| 突泉县| 禹州市| 皋兰县| 含山县| 新津县| 广水市| 堆龙德庆县| 新绛县| 融水| 淮安市| 景德镇市| 襄汾县| 新邵县| 调兵山市| 尚义县| 浦北县|