float存储原理

float占用4字节(32位),各bit的用途
  31位:符号位,正数为0,负数为1。
  23~30位:(指数部分,共8位):值减掉127后,表示小数点移动位数。比如:129表示小数点左移2位,124表示小数点右移3位。值为255有特殊用途,用于表示Infinity。
  0~22位:(尾数部分,共23位)
 
  0(111 1111 1)000 0000 0000 0000 0000 0000表示+Infinity
  1(111 1111 1)000 0000 0000 0000 0000 0000表示-Infinity
 

浮点数十进制转二进制过程
1,整数部分除2取余,直到商为0,然后逆序排列得到的余数,如:十进制12
  12/2=6 余0
  6/2=3 余0
  3/2=1 余1
  1/2=0 余1,商为0,停止
  得到的2进制就是1100

2,小数部分乘2取整,直到小数部分为0,然后顺序排列得到的整数。
  有可能小数部分一直不为0,那就根据精度来终止计算。如:十进制0.125
  0.125*2=0.25 整数部分0
  0.25*2=0.5 整数部分0
  0.5*2=1 整数部分1,小数部分0,停止
  得到的2进制就是001

3,将1和2得到的数据拼接。1的结果放在小数点左边,2的结果放在小数点右边。
  如:12.125的结果:1100.001

4,转为科学计数法。
  1100.001小数点左移3位,1.100001*(23)

5,得出最终二进制
  符号位:正数,所以是0
  指数部分:左移3位,所以是3+127=130,二进制为1000 0010
  尾数部分:先取小数点右侧的那部分(.100001),不足23位的补0,得到:1000 0100 0000 0000 0000 000
  最终结果:0 (100 0001 0)(100 0010 0000 0000 0000 0000)


根据二进制求出十进制float
例如:0(100 0001 0)(000 0100 0000 0000 0000 0000)
1)符号位(31位)
  0,即正数

2)求出指数(23~30位)
  指数=指数部分的值-127:1000 0010 - 127 = 130 - 127 = 3

3)尾数转小数:首位补1(为了节省空间,转换时去掉了首位的1,还原时需要补回来)
  1.000 0100 0000 0000 0000 0000

4)拼接小数和指数,即用科学计数法表示:
  1.000 0100 0000 0000 0000 0000*(23)
  即小数点右移3位:1000. 0100 0000 0000 0000 0000

整数部分:1000 = 1*23 + 0*22 + 0*21 + 0*20 = 8
小数部分:.01 = 0*(2-1) + 1*(2-2) = 1/4 = 0.25
所以结果为8+0.25=8.25
 
 
float转二进制工具函数
复制代码
/// float整数部分的二进制
public static string GetFloatBinString(int i)
{
    var sb = new StringBuilder();

    while (i > 1)
    {
        int bit = i % 2;
        i /= 2;
        sb.Insert(0, bit);
    }
    sb.Insert(0, i);
    return sb.ToString();
}

/// float小数部分的二进制
public static string GetFloatBinString2(string floatStr, int bitNum)
{
    int index = floatStr.IndexOf('.');
    if (index > 0)
    {
        int lastIndex = floatStr.Length - 1;
        char lastChar = floatStr[lastIndex];
        if ('f' == lastChar)
            lastIndex--;
        if (index + 1 <= lastIndex)
        {
            string s = floatStr.Substring(index + 1, lastIndex - index);
            var sb = new StringBuilder();
            int n = int.Parse(s);
            int n2 = (int)Math.Pow(10, s.Length);
            for (int i = 0; i < bitNum; ++i)
            {
                n = n * 2;
                if (n > n2)
                {
                    sb.Append('1');
                    n -= n2;
                }
                else
                {
                    sb.Append('0');
                }
                if (0 == n)
                    break;
            }
            return sb.ToString();
        }
    }
    return "";
}
复制代码

 

 
参考
 
posted @   yanghui01  阅读(80)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
点击右上角即可分享
微信分享提示