• ADADADADAD

    关于MYSQL中FLOAT和DOUBLE类型的存储[ mysql数据库 ]

    mysql数据库 时间:2024-12-03 12:14:24

    作者:文/会员上传

    简介:

    关于MYSQL中FLOAT和DOUBLE类型的存储


    其实在单精度和双精度浮点类型存储中其存储方式和C/C++一致准守IEEE标准他们都是浮点型的,所谓的浮点型,是小数点的位置可变,其能够表示

    以下为本文的正文内容,内容仅供参考!本站为公益性网站,复制本文以及下载DOC文档全部免费。

    关于MYSQL中FLOAT和DOUBLE类型的存储


    其实在单精度和双精度浮点类型存储中其存储方式和C/C++一致准守IEEE标准他们都是浮点型的,所谓的浮点型,是小数点的位置可变,其能够表示的范围比定点小数要广得多,而存储空间节省,但是受到精度的影响,所以在严格的数据中尽量使用定点小数mysql decimal(m,d)类型,ORACLE压根没有浮点数字类型而是number(p,s)定点小数,

    float 4字节
    18 23
    符号位指数位 尾数

    double 8字节
    111 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其额外的部分为无效数字

    实际上数据是没有问题的。
    关于MYSQL中FLOAT和DOUBLE类型的存储.docx

    将本文的Word文档下载到电脑

    推荐度:

    下载
    热门标签: Doublefloatmysql