1. <ul id="0c1fb"></ul>

      <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
      <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区

      RELATEED CONSULTING
      相關(guān)咨詢
      選擇下列產(chǎn)品馬上在線溝通
      服務(wù)時間:8:30-17:00
      你可能遇到了下面的問題
      關(guān)閉右側(cè)工具欄

      新聞中心

      這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
      java中數(shù)值范圍的精度丟失如何解決

      java中數(shù)值范圍的精度丟失如何解決?相信很多沒有經(jīng)驗的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。

      創(chuàng)新互聯(lián)成立與2013年,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項目成都網(wǎng)站設(shè)計、成都做網(wǎng)站網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元吐魯番做網(wǎng)站,已為上家服務(wù),為吐魯番各地企業(yè)和個人服務(wù),聯(lián)系電話:13518219792

      1.java中int,float,long,double取值范圍

      public class TestOutOfBound { 
      public static void main(String[] args) { 
       
      System.out.println(Integer.MAX_VALUE-(-Integer.MAX_VALUE)); //內(nèi)存溢出 
      System.out.println(Integer.MAX_VALUE); //2的31次方-1,10個數(shù)位,正的20億左右,用在錢上面不一定夠 
      System.out.println(Integer.MIN_VALUE); //負的2的31次方 
      System.out.println(Long.MAX_VALUE); //2的64次方-1,19個數(shù)位,很大了,可放心用在錢上面 
      System.out.println(Long.MIN_VALUE); //負的2的64次方 
      System.out.println(Float.MAX_VALUE); //2的128次方-1,38個數(shù)位,比long多了一倍,這個主要用來做簡單數(shù)學精確運算使用 
      System.out.println(Float.MIN_VALUE); //2的-149次方 
      System.out.println(Double.MAX_VALUE); //2的1024次方-1,308個數(shù)位,是float數(shù)位的10倍,主要用來做復(fù)雜運算和天文運算 
      System.out.println(Double.MIN_VALUE); //2的-1074次方 
       
      } 
      } 

      2.float與double精度丟失問題

      例子:

      舉例:double result = 1.0 - 0.9; 
       
      這個結(jié)果不用說了吧,都知道了,0.09999999999999998

      為什么會出現(xiàn)這個問題呢,就這是java和其它計算機語言都會出現(xiàn)的問題,下面我們分析一下為什么會出現(xiàn)這個問題:

      float和double類型主要是為了科學計算和工程計算而設(shè)計的。他們執(zhí)行二進制浮點運算,這是為了在廣泛的數(shù)字范圍上提供較為精確的快速近似計算而精心設(shè)計的。然而,它們并沒有提供完全精確的結(jié)果,所以我們不應(yīng)該用于精確計算的場合。float和double類型尤其不適合用于貨幣運算,因為要讓一個float或double精確的表示0.1或者10的任何其他負數(shù)次方值是不可能的(其實道理很簡單,十進制系統(tǒng)中能不能準確表示出1/3呢?同樣二進制系統(tǒng)也無法準確表示1/10)。

      浮點運算很少是精確的,只要是超過精度能表示的范圍就會產(chǎn)生誤差。往往產(chǎn)生誤差不是因為數(shù)的大小,而是因為數(shù)的精度。因此,產(chǎn)生的結(jié)果接近但不等于想要的結(jié)果。尤其在使用 float 和 double 作精確運算的時候要特別小心。

      現(xiàn)在我們就詳細剖析一下浮點型運算為什么會造成精度丟失?

      首先我們要搞清楚下面兩個問題: 
       
        (1) 十進制整數(shù)如何轉(zhuǎn)化為二進制數(shù) 
       
           算法很簡單。舉個例子,11表示成二進制數(shù): 
       
                11/2=5 余  1 
       
                 5/2=2  余  1 
       
                 2/2=1  余  0 
       
                 1/2=0  余  1 
       
                  0結(jié)束     11二進制表示為(從下往上):1011 
       
          這里提一點:只要遇到除以后的結(jié)果為0了就結(jié)束了,大家想一想,所有的整數(shù)除以2是不是一定能夠最終得到0。換句話說,所有的整數(shù)轉(zhuǎn)變?yōu)槎M制數(shù)的算法會不會無限循環(huán)下去呢?絕對不會,整數(shù)永遠可以用二進制精確表示 ,但小數(shù)就不一定了。 
       
        (2) 十進制小數(shù)如何轉(zhuǎn)化為二進制數(shù) 
       
           算法是乘以2直到?jīng)]有了小數(shù)為止。舉個例子,0.9表示成二進制數(shù) 
       
                0.9*2=1.8  取整數(shù)部分 1 
       
                0.8(1.8的小數(shù)部分)*2=1.6  取整數(shù)部分 1 
       
                0.6*2=1.2  取整數(shù)部分 1 
       
                0.2*2=0.4  取整數(shù)部分 0 
       
                0.4*2=0.8  取整數(shù)部分 0 
       
                0.8*2=1.6 取整數(shù)部分 1 
       
                0.6*2=1.2  取整數(shù)部分 0 
       
                    .........   0.9二進制表示為(從上往下): 1100100100100...... 
       
           注意:上面的計算過程循環(huán)了,也就是說*2永遠不可能消滅小數(shù)部分,這樣算法將無限下去。很顯然,小數(shù)的二進制表示有時是不可能精確的 。其實道理很簡單,十進制系統(tǒng)中能不能準確表示出1/3呢?同樣二進制系統(tǒng)也無法準確表示1/10。這也就解釋了為什么浮點型減法出現(xiàn)了"減不盡"的精度丟失問題。

      3.解決方法一:

      如果不介意自己記錄十進制的小數(shù)點,而且數(shù)值不大,那么可以使用long ,int等基本類型,具體用int還是long要看涉及的數(shù)值范圍大小,缺點是要自己處理十進制小數(shù)點,最明顯的做法就是處理貨幣使用分來計算,而不用元(只涉及加減)。

      如:

      int resultInt = 10 - 9;  
      double result = (double) resultInt / 100;//最終時候自己控制小數(shù)點  
      

      4.解決方法二:

      使用BigDecmal,而且需要在構(gòu)造參數(shù)使用String類型。

      在《Effective Java》這本書中就給出了一個解決方法。該書中也指出,float和double只能用來做科學計算或者是工程計算,在商業(yè)計算等精確計算中,我們要用java.math.BigDecimal。

      BigDecimal類一個有4個方法,我們只關(guān)心對我們解決浮點型數(shù)據(jù)進行精確計算有用的方法,即

      BigDecimal(double value) // 將double型數(shù)據(jù)轉(zhuǎn)換成BigDecimal型數(shù)據(jù)

      思路很簡單,我們先通過BigDecimal(double value)方法,將double型數(shù)據(jù)轉(zhuǎn)換成BigDecimal數(shù)據(jù),然后就可以正常進行精確計算了。等計算完畢后,我們可以對結(jié)果做一些處理,比如 對除不盡的結(jié)果可以進行四舍五入。最后,再把結(jié)果由BigDecimal型數(shù)據(jù)轉(zhuǎn)換回double型數(shù)據(jù)。

      這個思路很正確,但是如果你仔細看看API里關(guān)于BigDecimal的詳細說明,你就會知道,如果需要精確計算,我們不能直接用double,而非要用 String來構(gòu)造BigDecimal不可!所以,我們又開始關(guān)心BigDecimal類的另一個方法,即能夠幫助我們正確完成精確計算的 BigDecimal(String value)方法。
      // BigDecimal(String value)能夠?qū)tring型數(shù)據(jù)轉(zhuǎn)換成BigDecimal型數(shù)據(jù)

      那么問題來了,想像一下吧,如果我們要做一個浮點型數(shù)據(jù)的加法運算,需要先將兩個浮點數(shù)轉(zhuǎn)為String型數(shù)據(jù),然后用 BigDecimal(String value)構(gòu)造成BigDecimal,之后要在其中一個上調(diào)用add方法,傳入另一個作為參數(shù),然后把運算的結(jié)果(BigDecimal)再轉(zhuǎn)換為浮 點數(shù)。如果每次做浮點型數(shù)據(jù)的計算都要如此,你能夠忍受這么煩瑣的過程嗎?至少我不能。所以最好的辦法,就是寫一個類,在類中完成這些繁瑣的轉(zhuǎn)換過程。這 樣,在我們需要進行浮點型數(shù)據(jù)計算的時候,只要調(diào)用這個類就可以了。網(wǎng)上已經(jīng)有高手為我們提供了一個工具類Arith來完成這些轉(zhuǎn)換操作。它提供以下靜態(tài) 方法,可以完成浮點型數(shù)據(jù)的加減乘除運算和對其結(jié)果進行四舍五入的操作:

      public static double add(double v1,double v2)

      public static double sub(double v1,double v2)

      public static double mul(double v1,double v2)

      public static double div(double v1,double v2)

      public static double div(double v1,double v2,int scale)

      public static double round(double v,int scale)

      下面會附上Arith的源代碼,大家只要把它編譯保存好,要進行浮點數(shù)計算的時候,在你的源程序中導入Arith類就可以使用以上靜態(tài)方法來進行浮點數(shù)的精確計算了。

      附錄:Arith源代碼

      import java.math.BigDecimal; 
       
      /** 
      * 由于Java的簡單類型不能夠精確的對浮點數(shù)進行運算,這個工具類提供精 
      * 確的浮點數(shù)運算,包括加減乘除和四舍五入。 
      */ 
       
      public class Arith{ 
        //默認除法運算精度 
        private static final int DEF_DIV_SCALE = 10; 
        //這個類不能實例化 
        private Arith(){ 
        } 
       
        /** 
         * 提供精確的加法運算。 
         * @param v1 被加數(shù) 
         * @param v2 加數(shù) 
         * @return 兩個參數(shù)的和 
         */ 
        public static double add(double v1,double v2){ 
          BigDecimal b1 = new BigDecimal(Double.toString(v1)); 
          BigDecimal b2 = new BigDecimal(Double.toString(v2)); 
          return b1.add(b2).doubleValue(); 
        } 
        /** 
         * 提供精確的減法運算。 
         * @param v1 被減數(shù) 
         * @param v2 減數(shù) 
         * @return 兩個參數(shù)的差 
         */ 
        public static double sub(double v1,double v2){ 
          BigDecimal b1 = new BigDecimal(Double.toString(v1)); 
          BigDecimal b2 = new BigDecimal(Double.toString(v2)); 
          return b1.subtract(b2).doubleValue(); 
        } 
        /** 
         * 提供精確的乘法運算。 
         * @param v1 被乘數(shù) 
         * @param v2 乘數(shù) 
         * @return 兩個參數(shù)的積 
         */ 
        public static double mul(double v1,double v2){ 
          BigDecimal b1 = new BigDecimal(Double.toString(v1)); 
          BigDecimal b2 = new BigDecimal(Double.toString(v2)); 
          return b1.multiply(b2).doubleValue(); 
        } 
       
        /** 
         * 提供(相對)精確的除法運算,當發(fā)生除不盡的情況時,精確到 
         * 小數(shù)點以后10位,以后的數(shù)字四舍五入。 
         * @param v1 被除數(shù) 
         * @param v2 除數(shù) 
         * @return 兩個參數(shù)的商 
         */ 
        public static double div(double v1,double v2){ 
          return div(v1,v2,DEF_DIV_SCALE); 
        } 
       
        /** 
         * 提供(相對)精確的除法運算。當發(fā)生除不盡的情況時,由scale參數(shù)指 
         * 定精度,以后的數(shù)字四舍五入。 
         * @param v1 被除數(shù) 
         * @param v2 除數(shù) 
         * @param scale 表示表示需要精確到小數(shù)點以后幾位。 
         * @return 兩個參數(shù)的商 
         */ 
        public static double div(double v1,double v2,int scale){ 
          if(scale<0){ 
            throw new IllegalArgumentException( 
              "The scale must be a positive integer or zero"); 
          } 
          BigDecimal b1 = new BigDecimal(Double.toString(v1)); 
          BigDecimal b2 = new BigDecimal(Double.toString(v2)); 
          return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); 
        } 
       
        /** 
         * 提供精確的小數(shù)位四舍五入處理。 
         * @param v 需要四舍五入的數(shù)字 
         * @param scale 小數(shù)點后保留幾位 
         * @return 四舍五入后的結(jié)果 
         */ 
        public static double round(double v,int scale){ 
       
          if(scale<0){ 
            throw new IllegalArgumentException( 
              "The scale must be a positive integer or zero"); 
          } 
          BigDecimal b = new BigDecimal(Double.toString(v)); 
          BigDecimal one = new BigDecimal("1"); 
          return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); 
        } 
      }; 

      看完上述內(nèi)容,你們掌握java中數(shù)值范圍的精度丟失如何解決的方法了嗎?如果還想學到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!


      文章題目:java中數(shù)值范圍的精度丟失如何解決
      文章出自:http://www.ef60e0e.cn/article/piccpj.html
      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区
      1. <ul id="0c1fb"></ul>

        <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
        <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

        万山特区| 曲周县| 历史| 昌江| 沅江市| 沁水县| 姚安县| 和林格尔县| 普格县| 紫金县| 长葛市| 阿克| 万山特区| 泾阳县| 浪卡子县| 大名县| 平南县| 柳河县| 台南县| 东明县| 陆良县| 阜南县| 若尔盖县| 突泉县| 商城县| 淄博市| 金乡县| 奉节县| 贺州市| 吉安县| 晋江市| 陵川县| 信宜市| 海安县| 迁西县| 江门市| 类乌齐县| 贺兰县| 叶城县| 北碚区| 北川|