关于浮点数的二进制十六进制表示及转换
记录一下如何将二进制、十六进制表示的浮点数转换成十进制。...
在开发
Fun-multiplier For WeChat 微信功能加强插件时,查看了大量的微信反编译代码,其中涉及到浮点数的传值时,会发现其数值好像都很大,比如在32位arm汇编里的如下代码:
movs r2, 0x0首先需要知道,
movt r2, 0x41B4
movs r2, 0x0是把r2置为0,
movt r2, 0x41B4是把r2的高16位置为0x41B4,因此最终r2的值为0x41B40000。如果把它看成一个32位整型,则其值为1102315520,而如果将其看成32位的浮点数,则其值为22.5,现就其二进制的表示方式和转换方法记录如下。
根据国际标准IEEE 754,任意一个二进制浮点数V可以表示成下面的形式:
V = (-1)^S * M * 2^E
其中
- (-1)^S 表示符号位,当S=0,V为正数,当S=0时,V为负数。
- M表示有效数字,大于等于1,小于2。
- 2^E 表示指数位。
1.01101 * 2^4,下面以32位浮点数举例如何将0x41B40000转换成22.5这个浮点数。
首先,先将0x41B40000转换成二进制:
4 1 B 4 0 0 0 0其次,IEEE 754规定,对于32位的浮点数,最高的1位是符号位S,接着的8位是指数E,剩下的23位为有效数字M。因此,对以上二进制串重新排列:
0100 0001 1011 0100 0000 0000 0000 0000
S E M第三,IEEE 754还规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分。比如保存1.01的时候,只保存01,等到读取的时候,再把第一位的1加上去。这样做的目的,是节省1位有效数字。以32位浮点数为例,留给M只有23位,将第一位的1舍去以后,等于可以保存24位有效数字。对于E,E为一个无符号整数(unsigned int)。这意味着,如果E为8位,它的取值范围为0~255;如果E为11位(64位浮点数),它的取值范围为0~2047。但是,我们知道,科学计数法中的E是可以出现负数的,所以IEEE 754规定,E的真实值必须再减去一个中间数,对于8位的E,这个中间数是127。需要注意,如果E为全0,则有效数字M不沿用第二条说的规则前面加个1,而是还原为0.xxxxx的小数,主要目的是为了表示±0,以及接近于0的很小的数字。
0 10000011 01101000000000000000000
因此,对于
0 10000011 01101000000000000000000,S=0,E=10000011-01111111=00000100(十进制数为4),M=1.01101,则
V=1.01101 * 2^4 = 10110.1,即为22.5。
因为经常需要将十六进制浮点数转换成十进制,于是便自己用Python个转换的小程序(注意由于是自己用的小程序,故没有对输入进行合法性判断,也没有考虑E全0或者全1的情况) :
query = str(bin(int(raw_input(), 16)))[2:]如果还不错,可以支持一下我
[b]if[/b](len(query) < 32):
query = '0' * (32-len(query)) + query
s = 1 [b]if[/b] query[0] == '0' [b]else[/b] -1
e = int(query[1:9], 2) - 127
query = '1' + query[9:]
res, a = 0, 2**e
[b]for[/b] i [b]in[/b] query:
[b] if[/b](i == '1'):
res += a
a /= 2.0
print(s*res)
欢迎关注我的公众号和博客。
点击阅读原文进行留言。
关注 编程之道
微信扫一扫关注公众号