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 "";
}
参考
【C#】浮点数存储原理浅析 - 知乎
float类型在内存中的存储方式_float在内存中如何存储-CSDN博客
float在内存中如何存储? - 彼岸Elan - 博客园
关于lua的math.huge有多大的问题-CSDN博客
lua number上限值 lua number 精度_mob64ca14137e4f的技术博客_51CTO博客
C# float浮点数与二进制相互转换(IEEE754) - 冰封百度的学习笔记 - SegmentFault 思否
C#浮点数的表示和基本运算_C#教程_脚本之家