updated:

浮点数的机器级表示


一.将浮点数转换为二进制,规则在这里

#一段简单的python代码,将浮点数转换为二进制,注意该方案在遇到无限循环小数时存在误差 import re import math src = input() part = re.split(r'\.', src) part[0] = int(part[0]) part[1] = float('0.' + part[1]) part1 = [] part2 = [] while part[0] >= 1: tmp = part[0] % 2 part1.append(tmp) part[0] = int((part[0] - tmp) / 2) while part[1] > 0: tmp = math.floor(part[1] * 2) part2.append(tmp) part[1] = part[1] * 2 - tmp for i in range(0, len(part1)): print(part1[len(part1) - i - 1], end="") print(".", end="") for i in range(0, len(part2)): print(part2[i], end="")

二.浮点数在内存中的存放方式

根据国际标准IEEE 754,任意一个二进制浮点数V可以表示成下面的形式:

[latexpage] \[V=(-1)^s \times M \times 2^E\] 其中\((-1)^s\)表示符号位,当\(s=0\)时,\(V\)为正数;当\(s=1\)时,\(V\)为负数;\(M\)表示尾数,且满足\(1 \leq M < 2\)或\(0 \leq M < 1\);\(2^E\)表示指数位。 为了将浮点数存放在内存中,我们需要使用一中的算法将浮点数转化成二进制数。比如为了将\(13.625\)存入内存,先将\(13.625\)转化为二进制,即\(1101.101\) ,用科学计数法可以表示为 \(1.101101 \times 2^3\)。 在这个例子中,\(s\)取\(0\),因为这个数值为正数,尾数为\(101101\),\(E\)为3。 注意在使用科学计数法表示这一二进制数时小数点前的数字一般为\(1\),因此存储时不需要存储这一位,可以节省空间。

在计算机内存中,C语言的单精度浮点数占据32位,分为3个字段,分别为符号位s,编码E的8位阶码字段和编码尾数M的23位小数字段。它们具体的存储方式下面分情况讨论:

1.当阶码域是规格化的值(不全为零也不全为一)时,内存中存储的数值设为e,则E = e - Bias(偏置值,单精度是127)。因为e占八位,所以e的值是1~254,故E的范围是-126~127(别忘了E是规格化的)

2.当阶码域是非规格化的时,即全零,那么E = 1 - Bias。而且此时M不再加上前一位的1,它提供了一种表示0的方法。

3.当阶码域全为1时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);如果有效数字M不全为0,表示这个数不是一个数(NaN)。

现在做一个实验,代码如下:

0.19921875转二进制可以得到0.00110011,即1.10011。可以看到s = 0,E为-3,因此阶码域为01111100,尾数域是10011000000000000000000。因此a的位置应该存放的二进制串为00111110010011000000000000000000,转化为16进制为3E 4C 00 00

现在看看程序a的位置是什么

这里正是00 00 4C 3E,大多数系统按照“小端法”存储数据,因此反过来就得到了我们刚刚推得的值。


← Prev PHP反序列化漏洞 | 使用clang创建和使用动态库 Next →