你可能不知道的MySQL中的定點數類型

定點數類型

正由於用浮點數表示小數可能會有不精確的狀況,在一些狀況下咱們必須保證小數是精確的,因此設計MySQL的大叔們提出一種稱之爲定點數的數據類型,它也是存儲小數的一種方式:設計

其中:3d

  • M表示該小數最多須要的十進制有效數字個數。

注意是有效數字個數,比方說對於小數**-2.3來講有效數字個數就是2,對於小數0.9來講有效數字個數就是1**。code

  • D表示該小數的小數點後的十進制數字個數。

這個好理解,小數點後有幾個十進制數字,D的值就是什麼。blog

舉個例子看一下,設置了MD的單精度浮點數的取值範圍的變化:數據類型

能夠看到,在D相同的狀況下,M越大,該類型的取值範圍越大;在M相同的狀況下,D越大,該類型的取值範圍越小。固然,MD的取值也不是無限大的,M的取值範圍是1~255D的取值範圍是0~30,並且D的值必須不大於MMD都是可選的,若是咱們省略了它們,那它們的值按照機器支持的最大值來存儲。二進制

咱們說定點數是一種精確的小數,爲了達到精確的目的咱們就不能把它轉換成二進制小數以後再存儲(由於有不少十進制小數轉爲二進制小數後須要進行舍入操做,致使二進制小數表示的數值是不精確的)。其實轉念一想,所謂的小數只是把兩個十進制整數用小數點分割開來而已,咱們只要把小數點左右的兩個十進制整數給存儲起來,那不就是精確的了麼。比方說對於十進制小數2.38來講,咱們能夠把這個小數的小數點左右的兩個整數,也就是238分別保存起來,那麼不就至關於保存了一個精確的小數麼,這波操做是否是很6。im

固然事情並無這麼簡單,對於給定M、D值的**DECIMAL(M, D)類型,好比DEMCIMAL(16, 4)**來講:數據

  • 首先肯定小數點左邊的整數最多須要存儲的十進制位數是12位,小數點右邊的整數須要存儲的十進制位數是4位,如圖所示:

  • 從小數點位置出發,每一個整數每隔9個十進制位劃分爲1組,效果就是這樣:

從圖中能夠看出,若是不足9個十進制位,也會被劃分紅一組。img

  • 針對每一個組中的十進制數字,將其轉換爲二進制數字進行存儲,根據組中包含的十進制數字位數不一樣,所需的存儲空間大小也不一樣,具體見下表:

因此DECIMAL(16, 4)共須要佔用8個字節的存儲空間大小,這8個字節由下邊3個部分組成:co

  1. 第1組包含3個十進制位,須要使用2個字節存儲。
  2. 第2組包含9個十進制位,須要使用4個字節存儲。
  3. 第3組包含4個十進制位,須要使用2個字節存儲。
  • 將轉換完成的比特位序列的最高位設置爲1。

這些步驟看的有一丟丟懵逼吧,彆着急,舉個例子就都清楚了。比方說咱們使用定點數類型DECIMAL(16, 4)來存儲十進制小數1234567890.1234,這個小數會被劃分紅3個部分:

1 234567890 1234

也就是:

  1. 第1組中包含整數1。
  2. 第2組中包含整數234567890。
  3. 第3組中包含整數1234。

而後將每一組中的十進制數字轉換成對應的二進制數字:

  • 第1組佔用2個字節,整數1對應的二進制數就是(字節之間實際上沒有空格,只不過爲了你們理解上的方便咱們加了一個空格):
00000000 00000001

二進制看起來太難受,咱們仍是轉換成對應的十六進制看一下:

0x0001
  • 第2組佔用4個字節,整數234567890對應的十六進制數就是:
0x0DFB38D2
  • 第3組佔用2個字節,整數1234對應的十六進制數就是:
0x04D2

因此將這些十六進制數字連起來以後就是:

0x00010DFB38D204D2

最後還要將這個結果的最高位設置爲1,因此最終十進制小數1234567890.1234使用定點數類型**DECIMAL(16, 4)**存儲時共佔用8個字節,具體內容爲:

0x80010DFB38D204D2

有的朋友會問,若是咱們想使用定點數類型DECIMAL(16, 4)存儲一個負數怎麼辦,比方說-1234567890.1234,這時只須要將0x80010DFB38D204D2中的每個比特位都執行一個取反操做就好,也就是獲得下邊這個結果:

0x7FFEF204C72DFB2D

從上邊的敘述中咱們能夠知道,對於DECIMAL(M, D)類型來講,給定的MD的值不一樣,所需的存儲空間大小也不一樣。能夠看到,與浮點數相比,定點數須要更多的空間來存儲數據,因此若是不是在某些須要存儲精確小數的場景下,通常的小數用浮點數表示就足夠了。

對於定點數類型DECIMAL(M, D)來講,MD都是可選的,默認的M的值是10,默認的D的值是0,也就是說下列等式是成立的:

DECIMAL = DECIMAL(10) = DECIMAL(10, 0)
DECIMAL(n) = DECIMAL(n, 0)

另外M的範圍是1~65D的範圍是0~30,且D的值不能超過M

相關文章
相關標籤/搜索