mysql float精度與範圍總結 java
FLOAT類型用於表示近似數值數據類型。SQL標準 容許在關鍵字FLOAT後面的括號內選擇用位指定精度(但不能爲指數範圍)。MySQL還支持可選的只用於肯定存儲大小的精度規定。0到23的精度對應 FLOAT列的4字節單精度。24到53的精度對應DOUBLE列的8字節雙精度。 mysql
單精度浮點數用4字節(32bit)表示浮點數
採用IEEE754標準的計算機浮點數,在內部是用二進制表示的,如:7.22用32位二進制是表示不下的?因此就不精確了。
sql
對於浮點列類型,在MySQL中單精度值使用4個字節,雙精度值使用8個字節。 數據庫
FLOAT類型用於表示近似數值數據類型。SQL標準容許在關鍵字FLOAT後面的括號內選擇用位指定精度(但不能爲指數範圍)。MySQL還支持 可選的只用於肯定存儲大小的精度規定。0到23的精度對應FLOAT列的4字節單精度。24到53的精度對應DOUBLE列的8字節雙精度。 編程
MySQL容許使用非標準語法:FLOAT(M,D)或REAL(M,D)或DOUBLE PRECISION(M,D)。這裏,「(M,D)」表示該值一共顯示M位整數,其中D位位於小數點後面。例如,定義爲FLOAT(7,4)的一個列能夠 顯示爲-999.9999。MySQL保存值時進行四捨五入,所以若是在FLOAT(7,4)列內插入999.00009,近似結果是999.0001。 服務器
MySQL將DOUBLE視爲DOUBLE PRECISION(非標準擴展)的同義詞。MySQL還將REAL視爲DOUBLE PRECISION(非標準擴展)的同義詞,除非SQL服務器模式包括REAL_AS_FLOAT選項。 oracle
爲了保證最大可能的可移植性,須要使用近似數值數據值存儲的代碼應使用FLOAT或DOUBLE PRECISION,不規定精度或位數。 測試
DECIMAL和NUMERIC類型在MySQL中視爲相同的類型。它們用於保存必須爲確切精度的值,例如貨幣數據。當聲明該類型的列時,能夠(而且一般要)指定精度和標度;例如: spa
salary DECIMAL(5,2)
在該例子中,5是精度,2是標度。精度表示保存值的主要位數,標度表示小數點後面能夠保存的位數。 .net
在MySQL 5.1中以二進制格式保存DECIMAL和NUMERIC值。
標準SQL要求salary列可以用5位整數位和兩位小數保存任何值。所以,在這種狀況下能夠保存在salary列的值的範圍是從-999.99到999.99。
在標準SQL中,語法DECIMAL(M)等價於DECIMAL(M,0)。一樣,語法DECIMAL等價於DECIMAL(M,0),能夠經過計算肯定M的值。在MySQL 5.1中支持DECIMAL和NUMERIC數據類型的變量形式。M默認值是10。
DECIMAL或NUMERIC的最大位數是65,但具體的DECIMAL或NUMERIC列的實際範圍受具體列的精度或標度約束。若是此類列分配 的值小數點後面的位數超過指定的標度容許的範圍,值被轉換爲該標度。(具體操做與操做系統有關,但通常結果均被截取到容許的位數)。
2、mysql 和 oracle中的數值類型
問題是否是隻有 mysql 存在呢?顯然不是,只要是符合IEEE754標準的浮點數實現,都存在相同的問題。
mysql中的數值類型(不包括整型):
IEEE754浮點數:float(單精度),double或real(雙精度)
定點數:decimal或numeric
oracle中的數值類型:
oracle 浮點數 :number(注意不指定精度)
IEEE754浮點數:BINARY_FLOAT(單精度),BINARY_DOUBLE(雙精度)FLOAT,FLOAT(n) (ansi要求的數據類型)
定點數:number(p,s)
若是在oracle中,用BINARY_FLOAT等來作測試,結果是同樣的。所以,在數據庫中,對於涉及貨幣或其餘精度敏感的數據,應使用定點數來存 儲,對mysql來講是 decimal,對oracle來講就是number(p,s)。雙精度浮點數,對於比較大的數據一樣存在問題!
3、編程中也存在浮點數問題
不光數據庫中存在浮點數問題,編程中也一樣存在,甚至能夠說更值得引發注意!
經過上面的介紹,浮點數的偏差問題應該比較清楚了。若是在程序中作複雜的浮點數運算,偏差還會進一步放大。所以,在程序設計中,若是用到浮點數,必定要意 識到可能產生的偏差問題。不只如此,浮點數若是處理很差,還會致使程序BUG!看下面的語句:if (x != y) { z = 1 / (x -y);}這個語句看起來沒有問題,但若是是浮點數,就可能存在問題!再看下面的語句會輸出什麼結果: public class Test { public static void main(String[]args) throws Exception { System.out.print("7.22-7.0=" + (7.22f-7.0f)); } } 咱們可能會想固然地認爲輸出結果應該是 0.22 ,實際結果倒是 0.21999979 !
所以,在編程中應儘可能避免作浮點數的比較,不然可能會致使一些潛在的問題!除了這些,還應注意浮點數中的一些特殊值,如 NaN、+0、-0、+無窮、-無窮等,IEEE754雖然對此作了一些約定,但各具體實現、不一樣的硬件結構,也會有一些差別,若是不注意也會形成錯誤! 4、總結:
從上面的分析,咱們能夠得出如下結論:
一、浮點數存在偏差問題;
二、對貨幣等對精度敏感的數據,應該用定點數表示或存儲;
三、編程中,若是用到浮點數,要特別注意偏差問題,並儘可能避免作浮點數比較;
四、要注意浮點數中一些特殊值的處理。
Mysql | Oracle | Java |
BIGINT | NUMBER(19,0) |
java.lang.Long
|
BIT | RAW |
byte[]
|
BLOB | BLOB RAW |
byte[]
|
CHAR | CHAR |
java.lang.String
|
DATE | DATE | java.sql.Date |
DATETIME | DATE | java.sql.Timestamp |
DECIMAL | FLOAT (24) |
java.math.BigDecimal
|
DOUBLE | FLOAT (24) | java.lang.Double |
DOUBLE PRECISION | FLOAT (24) | java.lang.Double |
ENUM | VARCHAR2 |
java.lang.String
|
FLOAT | FLOAT | java.lang.Float |
INT | NUMBER(10,0) |
java.lang.Integer
|
INTEGER | NUMBER(10,0) |
java.lang.Integer
|
LONGBLOB | BLOB RAW | byte[] |
LONGTEXT | CLOB RAW | java.lang.String |
MEDIUMBLOB | BLOB RAW | byte[] |
MEDIUMINT | NUMBER(7,0) |
java.lang.Integer
|
MEDIUMTEXT | CLOB RAW | java.lang.String |
NUMERIC | NUMBER | |
REAL | FLOAT (24) | |
SET | VARCHAR2 |
java.lang.String
|
SMALLINT | NUMBER(5,0) |
java.lang.Integer
|
TEXT | VARCHAR2 CLOB |
java.lang.String
|
TIME | DATE | java.sql.Time |
TIMESTAMP | DATE | java.sql.Timestamp |
TINYBLOB | RAW | byte[] |
TINYINT | NUMBER(3,0) | java.lang.Boolean |
TINYTEXT | VARCHAR2 | java.lang.String |
VARCHAR | VARCHAR2 CLOB | java.lang.String |
YEAR | NUMBER | java.sql.Date(日期設爲2月1日晚上2點) |