kalman03

          每天早上看一遍《福布斯》富翁排行榜,如果上面沒有我的名字,我就去學習......
          隨筆 - 22, 文章 - 0, 評論 - 86, 引用 - 0
          數據加載中……

          Java中浮點數的精度問題

          當您在計算Money的時候,請看好了?。。∫粨p失了別后悔?。?!

          現象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

              }

          現象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

          }

          描述:

          當我們使用一些“特殊的數字”進行運算時,或者調用BigDecimalnew BigDecimal(double val)進行構造的時候,將得到意想不到的結果。

          原因:

          Java中,浮點類型是依據IEEE754標準的。IEEE754定義了32位和64位雙精度兩種浮點二進制小數標準。采用二進制表示double,float等浮點數是不準確的。

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

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

          1、 通過String結合BigDecimal來轉換。

                 String val = "0.236";

                 //使用new BigDecimal(String val)進行構造

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

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

                 //小數的位數與構造參數的位數一致

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

          2、  通過移位結合BigDecimal來轉換

                 String val = "0.236";

                 //使用new BigDecimal(String val)進行構造

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

                 //向右移兩位

                 a = a.movePointRight(2);

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

          3、  使用保留小數位的方法來轉換

                 double result = 0.236*100;

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

                 //計算保留result小數點后四位,以此類推,1后面幾個零就是保留小數點后幾位數.如下保留兩位小數

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

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

          4、 使用DecimalFormat來確定小數點后位數

                 double val = 0.236*100;

                 //保留小數點后兩位,若保留三位為"#.000"

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

                 String str = df.format(val);

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

          5、-----方法很多,一個即可

          心得:

          處理這樣的精度問題方法很多,只要不是直接采用浮點數進行計算就行。

          附加:

          IEEE 754用科學記數法以底數為2的小數來表示浮點數。32位浮點數用1位表示數字的符號,用8位來表示指數,用23位來表示尾數,即小數部分。作為有符號整數的指數可以有正負之分。小數部分用二進制(底數2)小數來表示。對于64位雙精度浮點數,用1位表示數字的符號,用11位表示指數,52位表示尾數。如下兩個圖來表示:

          float(32):

          1位,符號位

          冪(8位)

          尾數(32位)

          double(64):

          1位,符號位

          冪(11位)

          尾數(52位)

          都是分為三個部分:

          (1)一個單獨的符號位s直接編碼符號s

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

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

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

          評論

          # re: Java中浮點數的精度問題  回復  更多評論   

          這。。。。。。

          凡是有點常識的人都知道,浮點型不能直接用來運算。。

          通常都是用大數型來進行運算的。。。
          2010-11-08 10:31 | 指尖流沙

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 慈利县| 康马县| 文安县| 彰武县| 巫山县| 奎屯市| 龙口市| 会宁县| 胶南市| 遂宁市| 互助| 饶河县| 上虞市| 太谷县| 阿合奇县| 房产| 卢龙县| 巴楚县| 黄陵县| 吐鲁番市| 大理市| 汾西县| 乡城县| 绍兴县| 甘谷县| 扬中市| 山丹县| 江油市| 手机| 定南县| 申扎县| 双鸭山市| 永川市| 米泉市| 临漳县| 盖州市| 云阳县| 临潭县| 平利县| 洮南市| 休宁县|