MySQL中Decimal類型和Float Double的區別 & BigDecimal與Double使用場景


 

MySQL中存在float,double等非標准數據類型,也有decimal這種標准數據類型。

其區別在於,float,double等非標准類型,在DB中保存的是近似值,而Decimal則以字符串的形式保存數值。
float,double類型是可以存浮點數(即小數類型),但是float有個壞處,當你給定的數據是整數的時候,那么它就以整數給你處理。這樣我們在存取貨幣值的時候自然遇到問題,我的default值為:0.00而實際存儲是0,同樣我存取貨幣為12.00,實際存儲是12。

幸好mysql提供了兩個數據類型:decimal,這種數據類型可以輕松解決上面的問題:decimal類型被 MySQL 以同樣的類型實現,這在 SQL92 標准中是允許的。他們用於保存對准確精度有重要要求的值,例如與金錢有關的數據。

數據定義

float(M,S) M為全長,S為小數點后長度。

 

數據庫類型和Java類型之間的關系:              

    DBC Type                            Java Type 
    CHAR                                     String 
    VARCHAR                              String 
    LONGVARCHAR                    String 
    NUMERIC                        java.math.BigDecimal 
    DECIMAL                         java.math.BigDecimal 
    BIT                                        boolean
    BOOLEAN                            boolean 
    TINYINT                                  byte 
    SMALLINT                              short 
    INTEGER                                int 
    BIGINT                                    long 
    REAL                                      float 
    FLOAT                                   double 
    DOUBLE                               double 
    BINARY                                 byte[] 
    VARBINARY                          byte[] 
    LONGVARBINARY                byte[] 
    DATE                                  java.sql.Date 
    TIME                                   java.sql.Time 
    TIMESTAMP                       java.sql.Timestamp 
    CLOB                                     Clob 
    BLOB                                     Blob 
    ARRAY                                  Array 
    DISTINCT                           mapping of underlying type 
    STRUCT                                Struct 
    REF                                        Ref  

 

項目中BigDecimal與Double使用場景

金額要用BigDecimal

金額計算不能用doube!!!!

金額計算必須用BigDecimal,下面對比一下用double 跟BigDecimal的區別。先看一個小例子:

請看題:

示例1

問, 結果是多少? 0.01?

No! 結果是0.009999999999999998!

為什么會這樣呢? 因為float和double都是浮點數, 都有取值范圍, 都有精度范圍. 浮點數與通常使用的小數不同, 使用中, 往往難以確定.

常見的問題是定義了一個浮點數, 經過一系列的計算, 它本來應該等於某個確定值, 但實際上並不是!

double相減會轉換成二進制,因double有效位數為 16位這就會出現存儲小數位數不夠的情況,這種情況下就會出現誤差,解決方法就是使用BigDecimal,它的有效長度足夠長可存儲小數位數。

因此可代替double來進行加減乘除, 金額必須是完全精確的計算, 故不能使用double或者float, 而應該采用java.math.BigDecimal.

加減乘除

兩個BigDecimal值應該怎樣進行加減乘除呢? +, -, *, / 這樣寫嗎? 不!

請看示例:

加減乘除使用了英文的加減乘除, 即add, substract, multiply和divide

大小比較

兩個BigDecimal值怎么比較大小呢? 能用>或者<嗎? 也不可以!

兩個BigDecimal值比較使用compareTo方法, 比較結果有-1, 0, 1, 分別表示小於, 等於, 大於; 對於0, 可以使用BigDecimal.ZERO表示!

四舍五入

 

簡化BigDecimal計算的小工具類

如果我們要做一個加法運算,需要先將兩個浮點數轉為String,然后夠造成BigDecimal,在其中一個上調用add方法,傳入另一個作為參數,然后把運算的結果(BigDecimal)再轉換為浮點數。

你能夠忍受這么煩瑣的過程嗎?

網上提供的工具類Arith來簡化操作。它提供以下靜態方法,包括加減乘除和四舍五入:   

 

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)  

  

定點數和浮點數的區別

在計算機系統的發展過程中,曾經提出過多種方法表達實數。典型的比如相對於浮點數的定點數(Fixed Point Number)。在這種表達方式中,小數點固定的位於實數所有數字中間的某個位置。

貨幣的表達就可以使用這種方式,比如 99.00 或者 00.99 可以用於表達具有四位精度(Precision),小數點后有兩位的貨幣值。由於小數點位置固定,所以可以直接用四位數值來表達相應的數值。

SQL 中的 NUMBER 數據類型就是利用定點數來定義的。還有一種提議的表達方式為有理數表達方式,即用兩個整數的比值來表達實數。

定點數表達法的缺點在於其形式過於僵硬,固定的小數點位置決定了固定位數的整數部分和小數部分,不利於同時表達特別大的數或者特別小的數。

最終,絕大多數現代的計算機系統采納了所謂的浮點數表達方式。這種表達方式利用科學計數法來表達實數,即用一個尾數(Mantissa ),一個基數(Base),一個指數(Exponent)以及一個表示正負的符號來表達實數。

比如 123.45 用十進制科學計數法可以表達為 1.2345 × 102 ,其中 1.2345 為尾數,10 為基數,2 為指數。浮點數利用指數達到了浮動小數點的效果,從而可以靈活地表達更大范圍的實數。

在MySQL中使用浮點數類型和定點數類型來表示小數。浮點數類型包括單精度浮點數(FLOAT型)和雙精度浮點數(DOUBLE型)。定點數類型就是DECIMAL型。MySQL的浮點數類型和定點數類型如下表所示:

類型名稱 字節數 負數的取值范圍 非負數的取值范圍
FLOAT 4 -3.402823466E+38~
-1.175494351E-38
0和1.175494351E-38~
3.402823466E+38
DOUBLE 8 -1.7976931348623157E+308~
-2.2250738585072014E-308
0和2.2250738585072014E-308~
1.7976931348623157E+308
DECIMAL(M,D)或DEC(M,D) M+2 同DOUBLE型 同DOUBLE型

從上表中可以看出,DECIMAL型的取值范圍與DOUBLE相同。但是,DECIMAL的有效取值范圍由M和D決定,而且DECIMAL型的字節數是M+2,也就是說,定點數的存儲空間是根據其精度決定的。

 MySQL

 BigDecimal在進行入庫時, 數據庫選擇decimal類型, 長度可以自定義, 如18; 小數點我們項目中用的是2, 保留2位小數. 此外還要注意的就是默認值, 一定寫成0.00, 不要用默認的NULL, 否則在進行加減排序等操作時, 會帶來轉換的麻煩!

`balance` decimal(18,2) DEFAULT '0.00' COMMENT '賬戶余額',



MySQL DECIMAL數據類型用於在數據庫中存儲精確的數值。我們經常將DECIMAL數據類型用於保留准確精確度的列,例如會計系統中的貨幣數據。

要定義數據類型為DECIMAL的列,請使用以下語法:

1
column_name   DECIMAL (P,D);

在上面的語法中:

  • P是表示有效數字數的精度。 P范圍為1〜65
  • D是表示小數點后的位數。 D的范圍是0~30。MySQL要求D小於或等於(<=)P

DECIMAL(P,D)表示列可以存儲D位小數的P位數。十進制列的實際范圍取決於精度和刻度。

與INT數據類型一樣,DECIMAL類型也具有UNSIGNEDZEROFILL屬性。 如果使用UNSIGNED屬性,則DECIMAL UNSIGNED的列將不接受負值。

如果使用ZEROFILL,MySQL將把顯示值填充到0以顯示由列定義指定的寬度。 另外,如果我們對DECIMAL列使用ZERO FILL,MySQL將自動將UNSIGNED屬性添加到列。

以下示例使用DECIMAL數據類型定義的一個叫作amount的列。

1
amount  DECIMAL (6,2);

在此示例中,amount列最多可以存儲6位數字,小數位數為2位; 因此,amount列的范圍是從-9999.999999.99








參考:
https://www.jb51.net/article/109363.htm
https://www.cnblogs.com/owenma/p/7991508.html
http://www.cnblogs.com/owenma/p/7097602.html


免責聲明!

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



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