手撕浮点数的存储形式

浮点数在内存中的存储形式是16进制,神明共睹,毋庸置疑。

那如何转换的呢?也许很多人没有想过,但对于某些IT “walker”来说想想再掌握或许更有意义,例如血量、弹药或者其它数据你想掰开内存之门去修改,而他们却用的是浮点数的存储,你不知道浮点数在内存中是如何存放的,形式是什么,那这个过程会很累。

有的人说我可以用工具转换,的确现在有很多工具可以进行转换,但这样你充其量也就是个工具人,俗称”脚本小子”。

工具一旦出现纰漏或者不可用了,那你也就歇菜了。

接下来具体说说是如何计算并转换成16进制的。

32位浮点数。

32位浮点数的组成:按从左到右的顺序分为三部分,[符号位][阶数][尾数]。

符号位。占1个bit

阶数。占8个bit

尾数。占23个bit

例如一个32位浮点数:100.25。我们看看如下计算过程:

符号位的计算: 正数为0,负数为1。

计算阶数和尾数之前,要先将小数点左右2边的数值转化成二进制,100=1100100,0.25=01(为什么是01文末进行解释并计算)。如此转化后,小数点左边是1100100,右边是01,即1100100.01。

阶数和尾数的计算:浮点数的整数部分转换成二进制,小数点左移到整数部分的长度-1的位置,例如整数部分是100转换成二进制是1100100,小数点左移到它的长度-1的位置,长度是7,7-1=6,就是1.100100,取小数点左边进行计算,1*(e+长度-1),32位浮点数的e取值是127,即1*(127+(7-1)=1*133=133,再将十进制133转化成二进制就是10000101,正好占8个bit,这就是阶数,可以看到是取的1.100100左边的1计算得出的阶数,那么小数点右边的100100就成了尾数,别忘了还有未左移前的小数点右边的2bit长度的尾数01,那么最终尾数就是计算阶数多出来的尾数和最开始的2bit的尾数,即10010001

最终填充各自的占位就是01000010110010001,右边还差15个bit才构成32bit,这15bit用0填充即可,最后就是01000010110010001000000000000000 转换成十六进制=0x42c88000,可以用python转换

%title插图%num

写一段代码验证一下内存中存储100.25是不是0x42c88000,如下图验证结果:

%title插图%num

完全一致。

64位浮点数同理。但是阶数和尾数的长度不同了

64位浮点数的组成:按从左到右的顺序分为三部分,[符号位][阶数][尾数]。

符号位。占1个bit

阶数。占11个bit

尾数。占52个bit

计算过程与32位浮点数同理。

文末知识补充:

前文说100.25计算阶数和尾数之前要先将小数点左右2边转换成二进制,小数点右边是25,由于是小数,所以是0.25,上文说0.25转换成二进制是01,现在我们说说为什么得出01,根据计算方法要将小数每次乘以2并取结果中的整数,直到小数为0,第一次0.25*2=0.5,取结果中的整数,第一次取到0,小数是0.5,第二次0.5*2=1.0,取结果中的整数,第二次取到的是1,小数是0.0即0,结束计算。那么0.25最后转换成二进制就是01。

发表回复