Java中基本數據類型、不能用浮點數表示金額


 

轉載請注明原文地址:https://www.cnblogs.com/ygj0930/p/10831763.html

 

一:8種基本數據類型

    8種基本數據類型(4整,2浮,1符,1布)

    整型:byte(最小的數據類型)、short(短整型)、int(整型)、long(長整型);

    浮點型:float(浮點型)、double(雙精度浮點型);

    字符型:char(字符型);

    布爾型:boolean(布爾型)。

 

 

二: 整型中 byte、short、int、long 取值范圍:記住存儲位數即可

    byte:一個字節有8位,去掉符號位還有7位,正數為避免進位還要減1,因此byte的取值范圍為:-2^7 ~ (2^7-1),也就是 -128~127 之間。

    short:short用16位存儲,去掉符號位還有15位,正數為避免進位還要減1,因此short的取值范圍是:-2^15 ~ (2^15-1)。

    int:整型用32位存儲,去掉符號位還有31位,正數為避免進位還要減1,因此整型的取值范圍是 -2^31 ~ (2^31-1)。

    long:長整型用64位存儲,去掉符號位還有63位,正數為避免進位還要減1,因此長整型的取值范圍是 -2^63 ~ (2^63-1)。

 

三:浮點型數據

    浮點類型是指用於表示小數的數據類型。

 

    單精度和雙精度的區別:

    單精度浮點型float,用32位存儲,1位為符號位, 指數8位, 尾數23位,即:float的精度是23位,能精確表達23位的數,超過就被截取。

    雙精度浮點型double,用64位存儲,1位符號位,11位指數,52位尾數,即:double的精度是52位,能精確表達52位的數,超過就被截取。

 

    雙精度類型double比單精度類型float具有更高的精度,和更大的表示范圍,常常用於科學計算等高精度場合。

 

    浮點數與小數的區別:

    1)在賦值或者存儲中浮點類型的精度有限,float是23位,double是52位。

    2)在計算機實際處理和運算過程中,浮點數本質上是以二進制形式存在的。

    3)二進制所能表示的兩個相鄰的浮點值之間存在一定的間隙,浮點值越大,這個間隙也會越大。如果此時對較大的浮點數進行操作時,浮點數的精度問題就會產生,甚至出現一些“不正常"的現象。

 

四:不能用浮點數來表示金額

   1)精度丟失問題  

    從上面我們可以知道,float的精度是23位,double精度是63位。在存儲或運算過程中,當超出精度時,超出部分會被截掉,由此就會造成誤差。

    對於金額而言,舍去不能表示的部分,損失也就產生了。
    

    2)進制轉換誤差

    從上面我們可以知道,在計算機實際處理和運算過程中,浮點數本質上是以二進制形式存在的。

    而十進制的0.1在二進制下將是一個無限循環小數,這就會導致誤差的出現。

    如果一個小數不是2的負整數次冪,用浮點數表示必然產生浮點誤差。

    換言之:A進制下的有限小數,轉換到B進制下極有可能是無限小數,誤差也由此產生。

 

    浮點數不精確的根本原因在於:尾數部分的位數是固定的,一旦需要表示的數字的精度高於浮點數的精度,那么必然產生誤差

   

    解決這個問題的方法是BigDecimal的類,這個類可以表示任意精度的數字,其原理是:用字符串存儲數字,轉換為數組來模擬大數,實現兩個數組的數學運算並將結果返回。

 

五:BigDecimal的使用要點

    1、BigDecimal變量初始化——必須用傳入String的構造方法

BigDecimal num1 = new BigDecimal(0.005);//用數值轉換成大數,有誤差
BigDecimal num12 = new BigDecimal("0.005");//用字符串轉換成大數,無誤差

    因為:不是所有的浮點數都能夠被精確的表示成一個double 類型值,有些浮點數值不能夠被精確的表示成 double 類型值時,它會被表示成與它最接近的 double 類型的值,此時用它來初始化一個大數,會“先造成了誤差,再用產生了誤差的值生成大數”,也就是“將錯就錯”。

 

    2、使用除法函數在divide的時候要設置各種參數,要精確的小數位數和舍入模式,其中有8種舍入模式:

1、ROUND_UP

遠離零的舍入模式。

在丟棄非零部分之前始終增加數字(始終對非零舍棄部分前面的數字加1)。

注意,此舍入模式始終不會減少計算值的大小。


2、ROUND_DOWN

接近零的舍入模式。

在丟棄某部分之前始終不增加數字(從不對舍棄部分前面的數字加1,即截短)。

注意,此舍入模式始終不會增加計算值的大小。


3、ROUND_CEILING

接近正無窮大的舍入模式。

如果 BigDecimal 為正,則舍入行為與 ROUND_UP 相同;

如果為負,則舍入行為與 ROUND_DOWN 相同。

注意,此舍入模式始終不會減少計算值。


4、ROUND_FLOOR

接近負無窮大的舍入模式。

如果 BigDecimal 為正,則舍入行為與 ROUND_DOWN 相同;

如果為負,則舍入行為與 ROUND_UP 相同。

注意,此舍入模式始終不會增加計算值。


5、ROUND_HALF_UP

向“最接近的”數字舍入,如果與兩個相鄰數字的距離相等,則為向上舍入的舍入模式。

如果舍棄部分 >= 0.5,則舍入行為與 ROUND_UP 相同;否則舍入行為與 ROUND_DOWN 相同。

注意,這是我們大多數人在小學時就學過的舍入模式(四舍五入)。


6、ROUND_HALF_DOWN

向“最接近的”數字舍入,如果與兩個相鄰數字的距離相等,則為上舍入的舍入模式。

如果舍棄部分 > 0.5,則舍入行為與 ROUND_UP 相同;否則舍入行為與 ROUND_DOWN 相同(五舍六入)。


7、ROUND_HALF_EVEN

向“最接近的”數字舍入,如果與兩個相鄰數字的距離相等,則向相鄰的偶數舍入。

如果舍棄部分左邊的數字為奇數,則舍入行為與 ROUND_HALF_UP 相同;

如果為偶數,則舍入行為與 ROUND_HALF_DOWN 相同。

注意,在重復進行一系列計算時,此舍入模式可以將累加錯誤減到最小。

此舍入模式也稱為“銀行家舍入法”,主要在美國使用。

如果前一位為奇數,則入位,否則舍去。

以下例子為保留小數點1位,那么這種舍入方式下的結果。

1.15>1.2 1.25>1.2


8、ROUND_UNNECESSARY

斷言請求的操作具有精確的結果,因此不需要舍入。

如果對獲得精確結果的操作指定此舍入模式,則拋出ArithmeticException。

 

六:BigDecimal源碼閱讀

    Todo。     

 

七:Todo

    大數運算的實現:https://www.cnblogs.com/hdwang/p/7642783.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM