【mysql】浮点类型
文章目錄
- 浮點(diǎn)類型
- 1. 類型介紹
- 2. 數(shù)據(jù)精度說明
- 3. 精度誤差說明
 
浮點(diǎn)類型
1. 類型介紹
-  浮點(diǎn)數(shù)和定點(diǎn)數(shù)類型的特點(diǎn)是可以處理小數(shù),你可以把整數(shù)看成小數(shù)的一個(gè)特例。因此,浮點(diǎn)數(shù)和定點(diǎn)數(shù)的使用場景,比整數(shù)大多了。 MySQL支持的浮點(diǎn)數(shù)類型,分別是 FLOAT、DOUBLE、REAL。 
-  FLOAT 表示單精度浮點(diǎn)數(shù); 
-  DOUBLE 表示雙精度浮點(diǎn)數(shù); 
- REAL默認(rèn)就是 DOUBLE。如果把 SQL 模式設(shè)定為啟用“REAL_AS_FLOAT”,那 么,MySQL 就認(rèn)為 REAL 是 FLOAT。如果要啟用“REAL_AS_FLOAT”,可以通過以下 SQL 語句實(shí)現(xiàn):
問題1: FLOAT 和 DOUBLE 這兩種數(shù)據(jù)類型的區(qū)別是什么?
FLOAT 占用字節(jié)數(shù)少,取值范圍小;DOUBLE 占用字節(jié)數(shù)多,取值范圍也大。
問題2: 為什么浮點(diǎn)數(shù)類型的無符號數(shù)取值范圍,只相當(dāng)于有符號數(shù)取值范圍的一半,也就是只相當(dāng)于有符號數(shù)取值范圍大于等于零的部分呢?
MySQL 存儲浮點(diǎn)數(shù)的格式為:符號(S)、尾數(shù)(M)和 階碼(E)。因此,無論有沒有符號,MySQL 的浮點(diǎn)數(shù)都會存儲表示符號的部分。因此, 所謂的無符號數(shù)取值范圍,其實(shí)就是有符號數(shù)取值范圍大于等于零的部分。
2. 數(shù)據(jù)精度說明
對于浮點(diǎn)類型,在MySQL中單精度值使用4個(gè)字節(jié),雙精度值使用8個(gè)字節(jié)。
-  MySQL允許使用非標(biāo)準(zhǔn)語法(其他數(shù)據(jù)庫未必支持,因此如果涉及到數(shù)據(jù)遷移,則最好不要這么用):FLOAT(M,D)或DOUBLE(M,D)。這里,M稱為精度,D稱為標(biāo)度。(M,D)中 M=整數(shù)位+小數(shù)位,D=小數(shù)位。 D<=M<=255,0<=D<=30。 例如,定義為FLOAT(5,2)的一個(gè)列可以顯示為-999.99-999.99。如果超過這個(gè)范圍會報(bào)錯(cuò)。 
-  FLOAT和DOUBLE類型在不指定(M,D)時(shí),默認(rèn)會按照實(shí)際的精度(由實(shí)際的硬件和操作系統(tǒng)決定)來顯示。 
-  說明:浮點(diǎn)類型,也可以加UNSIGNED,但是不會改變數(shù)據(jù)范圍,例如:FLOAT(3,2) UNSIGNED仍然只能表示0-9.99的范圍。 
-  不管是否顯式設(shè)置了精度(M,D),這里MySQL的處理方案如下: -  如果存儲時(shí),整數(shù)部分超出了范圍,MySQL就會報(bào)錯(cuò),不允許存這樣的值 
-  如果存儲時(shí),小數(shù)點(diǎn)部分若超出范圍,就分以下情況: - 若四舍五入后,整數(shù)部分沒有超出范圍,則只警告,但能成功操作并四舍五入刪除多余的小數(shù)位后保存。例如在FLOAT(5,2)列內(nèi)插入999.009,近似結(jié)果是999.01。
- 若四舍五入后,整數(shù)部分超出范圍,則MySQL報(bào)錯(cuò),并拒絕處理。如FLOAT(5,2)列內(nèi)插入999.995和-999.995都會報(bào)錯(cuò)。
 
 
-  
-  從MySQL 8.0.17開始,FLOAT(M,D) 和DOUBLE(M,D)用法在官方文檔中已經(jīng)明確不推薦使用,將來可能被移除。另外,關(guān)于浮點(diǎn)型FLOAT和DOUBLE的UNSIGNED也不推薦使用了,將來也可能被移除。 
-  舉例 
- 存在四舍五入問題
- 超出范圍,因?yàn)?f4(5,2),可以得知 整數(shù)位:3,小數(shù)位:2,1234.456 超出整數(shù)位的訪問了
- 小數(shù)位超過就四舍五入,整數(shù)位超了就報(bào)錯(cuò)了
 
3. 精度誤差說明
浮點(diǎn)數(shù)類型有個(gè)缺陷,就是不精準(zhǔn)。下面我來重點(diǎn)解釋一下為什么 MySQL 的浮點(diǎn)數(shù)不夠精準(zhǔn)。比如,我們設(shè)計(jì)一個(gè)表,有f1這個(gè)字段,插入值分別為0.47,0.44,0.19,我們期待的運(yùn)行結(jié)果是:0.47 + 0.44 + 0.19 = 1.1。而使用sum之后查詢:
CREATE TABLE test_double2( f1 DOUBLE );INSERT INTO test_double2 VALUES(0.47),(0.44),(0.19); mysql> SELECT SUM(f1)-> FROM test_double2; +--------------------+ | SUM(f1) | +--------------------+ | 1.0999999999999999 | +--------------------+ 1 row in set (0.00 sec) mysql> SELECT SUM(f1) = 1.1,1.1 = 1.1-> FROM test_double2; +---------------+-----------+ | SUM(f1) = 1.1 | 1.1 = 1.1 | +---------------+-----------+ | 0 | 1 | +---------------+-----------+ 1 row in set (0.00 sec)-  查詢結(jié)果是 1.0999999999999999。看到了嗎?雖然誤差很小,但確實(shí)有誤差。 你也可以嘗試把數(shù)據(jù)類型改成 FLOAT,然后運(yùn)行求和查詢,得到的是, 1.0999999940395355。顯然,誤差更大了。 
-  那么,為什么會存在這樣的誤差呢?問題還是出在 MySQL 對浮點(diǎn)類型數(shù)據(jù)的存儲方式上。 
-  MySQL 用 4 個(gè)字節(jié)存儲 FLOAT 類型數(shù)據(jù),用 8 個(gè)字節(jié)來存儲 DOUBLE 類型數(shù)據(jù)。無論哪個(gè),都是采用二進(jìn)制的方式來進(jìn)行存儲的。比如 9.625,用二進(jìn)制來表達(dá),就是 1001.101,或者表達(dá)成 1.001101×2^3。如果尾數(shù)不是 0 或 5(比如 9.624),你就無法用一個(gè)二進(jìn)制數(shù)來精確表達(dá)。進(jìn)而,就只好在取值允許的范圍內(nèi)進(jìn)行四舍五入。 
-  在編程中,如果用到浮點(diǎn)數(shù),要特別注意誤差問題,因?yàn)楦↑c(diǎn)數(shù)是不準(zhǔn)確的,所以我們要避免使用“=”來判斷兩個(gè)數(shù)是否相等。 同時(shí),在一些對精確度要求較高的項(xiàng)目中,千萬不要使用浮點(diǎn)數(shù),不然會導(dǎo)致結(jié)果錯(cuò)誤,甚至是造成不可挽回的損失。那么,MySQL 有沒有精準(zhǔn)的數(shù)據(jù)類型呢?當(dāng)然有,這就是定點(diǎn)數(shù)類型:DECIMAL。 
總結(jié)
以上是生活随笔為你收集整理的【mysql】浮点类型的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: gmtime() php,C语言gmti
- 下一篇: MAC打开outlook提示”正在修复
