關於MySQL中FLOAT和DOUBLE類型的儲存

來源:互聯網
上載者:User

關於MySQL中FLOAT和DOUBLE類型的儲存

其實在單精確度和雙精確度浮點類型儲存中其儲存方式和C/C++一致准守IEEE標準他們都是浮點型的,所謂的浮點型,是小數點的位置可變,其能夠表示的範圍比定點小數要廣得多,而儲存空間節省,但是受到精度的影響,所以在嚴格的資料中盡量使用定點小數mysql decimal(m,d)類型,Oracle壓根沒有浮點數字類型而是number(p,s)定點小數,

float 4位元組
    1      8      23
  符號位  指數位 尾數

double 8位元組
    1      11    52
    符號位  指數位  尾數
 那麼很明顯他們的精度取決於尾數。
 而表示的範圍取決於指數。

float表示範圍:
2^8=(-128—127)
-2^128—2^127
約為-3.4E38—3.4E38
 double表示範圍:
2^11=(-1024—1023)
-2^1024—2^1023
約為-1.7E308—1.7E308
可以看到這個範圍實際上很廣,但是精度確很小
float精度:
float 尾數23位,2^23=8.3E6  6-7位
double尾數52位,2^52=4.5E15 14-15位

 那麼如果使用浮點數據儲存了精度大於其範圍的資料其會使用四捨五入的方法截斷。
MYSQL如下:
mysql> create table dname(id1 float,id2 double,name varchar(20));
 Query OK, 0 rows affected (0.08 sec)
 mysql> insert into dname values(1234567.123,1234567.123,'gaopeng');
 Query OK, 1 row affected (0.00 sec)
 mysql> commit;
 Query OK, 0 rows affected (0.00 sec)
 mysql> select * from dname;
 +---------+-------------+---------+
 | id1    | id2        | name    |
 +---------+-------------+---------+
 | 1234570 | 1234567.123 | gaopeng |
 +---------+-------------+---------+
 1 row in set (0.00 sec)
雖然進行了四捨五入,但是不會有任何報錯和警告,這是其標準決定的而不是資料庫本生。
 可以看到1234567.123在FLOAT下被四捨五入為1234570,而DOUBLE類型沒有問題,那麼我們
 直接從資料檔案中提取資料。
 我還是使用了自己寫的小工具BCVIEW
 [root@Hadoop1 test]# bcview dname.ibd 16 127 40
 ******************************************************************
 This Tool Is Uesed For Find The Data In Binary format(Hexadecimal)
 Usage:./bcview file blocksize offset cnt-bytes!                 
 file: Is Your File Will To Find Data!                           
 blocksize: Is N kb Block.Eg: 8 Is 8 Kb Blocksize(Oracle)!       
                          Eg: 16 Is 16 Kb Blocksize(Innodb)!     
 offset:Is Every Block Offset Your Want Start!                                   
 cnt-bytes:Is After Offset,How Bytes Your Want Gets!                             
 Edtor QQ:22389860!                                               
 Used gcc version 4.1.2 20080704 (Red Hat 4.1.2-46)               
 ******************************************************************
 ----Current file size is :0.093750 Mb
 ----Current use set blockszie is 16 Kb
 current block:00000000--Offset:00127--cnt bytes:40--data is:00ffffffff0000000000010000000200260000000200260000000000000000ffffffff0000ffffff
 current block:00000001--Offset:00127--cnt bytes:40--data is:00000000000000000000000000000000000000000000000000000000000000000000000000000000
 current block:00000002--Offset:00127--cnt bytes:40--data is:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
 current block:00000003--Offset:00127--cnt bytes:40--data is:000001cc6d090000002d5679ab00000d0c011039b4964991ed7c1f87d6324167616f70656e670000
 current block:00000004--Offset:00127--cnt bytes:40--data is:00000000000000000000000000000000000000000000000000000000000000000000000000000000
 current block:00000005--Offset:00127--cnt bytes:40--data is:00000000000000000000000000000000000000000000000000000000000000000000000000000000

實際的資料是
000001cc6d09        rowid       
 0000002d5679ab      事物ID         
 00000d0c0110        復原指標         
39b49649            1234570     
 91ed7c1f87d63241    1234567.123 
 67616f70656e67      'gaopeng'   
關於如何得到資料的可以參考我的博文
http://blog.itpub.net/7728585/viewspace-2071787/
我們來分析下float的組成,因為LINUX屬於小端,儲存會是反向的
39b49649實際是4996b439

 49 01001001
 96 10010110
 b4 10110100
 39 00111001

    0    10010011    00101101011010000111001
符號位  指數位            尾數

10010011=147
這裡需要減去127
 147-127=20為指數

 尾數 00101101011010000111001需要加入一個1.
如下1.00101101011010000111001
如此我們需要將1.00101101011010000111001
乘以2的20次方實際就是右移動20位
 為
100101101011010000111.001
整數部分
100101101011010000111=1234567這裡就是最後的資料1234567
而顯示的時候1234567又被四捨五入為1234570

再來看double

 91ed7c1f87d63241
實際為
4132d6871f7ced91

 0                          符號位
10000010011  1043 然後1043-1023=20 級指數位
0010110101101000011100011111011111001110110110010001

1.0010110101101000011100011111011111001110110110010001
 100101101011010000111.00011111011111001110110110010001


整數部分為100101101011010000111=1234567
關於小數部分的計算:
0*2^(0-1) 第一位
0*2^(0-2) 第二位
0*2^(0-3) 第三位
1*2^(0-4)=1/16 第四位
1*2^(0-5)=1/32 第五位
1*2^(0-6)=1/64 第六位
.....
及0.123=0.0001111101111100其額外的部分為無效數字

實際上資料是沒有問題的。

本文永久更新連結地址:

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.