美文网首页
二进制小数与浮点数的存储

二进制小数与浮点数的存储

作者: 李不言被占用了 | 来源:发表于2023-08-31 09:35 被阅读0次

    小数二进制的转换和浮点数的存储是两个不太相关的内容,所以本文分两个主题分别记录。

    进制转换

    十进制整数转二进制

    除二取余法,余数倒排。
    原理来源于:
    十进制:123=1*10^{2}+2*10^{1}+3*10^{0}
    二进制:1011=1*2^{3}+0*2^{2}+1*2^{1}+1*2^{0} = 11
    反向求解的时候就是除2(基数)取余。

    11 ÷ 2 = 5 余 1
    5 ÷ 2 = 2 余 1
    2 ÷ 2 = 1 余 0
    1 ÷ 2 = 0 余 1
    得到二进制:1011
    

    十进制小数转二进制

    乘二取整。
    原理来源于:
    十进制:0.123=1*10^{-1}+2*10^{-2}+3*10^{-3}
    二进制:0.1011=1*2^{-1}+0*2^{-2}+1*2^{-3}+1*2^{-4} = 0.6825
    反向求解的时候就是乘2(基数)取整:

    0.6825 * 2 = 1.375  拿走整数部分1,剩0.375
    0.375 * 2 = 0.75  拿走整数部分0,剩0.75
    0.75 * 2 = 1.5 拿走整数部分1,剩0.5
    0.5 * 2 = 1 拿走整数部分1,剩0,结束
    得到二进制:0.1011
    

    通过上面的运算可以知道:11.6825转成二进制是:1011.1011
    另外一个规律:小数尾数为5(x.5、x.25、x.xxxxx5)才能用完整的二进制表示,不然一直乘2小数部分永远不能为0。
    快速运算:

    0.1(二进制)=0.5(十进制)
    0.01(二进制)=0.25(十进制)
    0.001(二进制)=0.125(十进制)
    ……
    

    小数存储

    我们假设,小数点存储在中间,假设用8bit来存储小数:
    1011 1011就等于1011.1011。用16bit来存储小数:0000 1011 1011 0000就等于1011.1011。
    以上只是我们的假设,为了统一,现在计算机都采用IEEE 754的标准来存储小数(浮点数)。有单精度(32bit)和双精度(64bit)两种。

    image.png

    统一公式:V=(-1)^s*2^{E}*M
    其中s为符号位,E为阶码,M为尾数。
    s为所见即所得,0正数,1负数。
    E为移码表示,移Bias=2^{N-1}-1,相当于加上2^{N-1}-1,Bias称偏移量。
    M为尾数,隐藏最高位1,相当于计算尾数时,要加上1。

    以0.4375为例,因为M尾数最高位要为1,也就是我们要想办法让0.4375表示成1.xxx * 2^{E}的形式:0.4375 = 1.75 * 2^{-2}
    用单精度表示,偏移量为2^ {8-1} -1 = 127
    0.4375 = (-1)^{0} * 2^{-2+127} * 1.75 = 2^{125} * 1.75
    现在的任务变成了将125和1.75(需要隐藏高位1,变成0.75)转换成二进制:
    125 = 0111 1101(8位)0.75 = 1100 0000 0000 0000 000(23位)
    所以0.4375的浮点数表示就是:0011 11110 1110 0000 0000 0000 0000 0000

    image.png
    在线转换网址

    同理,将0011 11110 1110 0000 0000 0000 0000 0000 转换成小数就是:

    阶数:0111 1101 = 125,实际 125 - 127(偏移量) = -2
    尾数:1100 0000 0000 0000 000 = 0.11(二进制) = 0.5+0.25=0.75(十进制)
    尾数补隐藏位1:1+0.75=1.75
    

    原小数:-1^{0} * 2^{-2} * 1.75 = 0.4375

    双精度浮点数的偏移量:2^{11-1} -1 =1023

    利用java转换

    long l = Double.doubleToLongBits(0.4375);
    System.out.println(l);
    // 11111111011100000000000000000000000000000000000000000000000000
    System.out.println(Long.toBinaryString(l));
    
    Long aLong = Long.valueOf("11111111011100000000000000000000000000000000000000000000000000", 2);
    double v = Double.longBitsToDouble(aLong);
    // 0.4375
    System.out.println(v);
    

    相关文章

      网友评论

          本文标题:二进制小数与浮点数的存储

          本文链接:https://www.haomeiwen.com/subject/juqyedtx.html