我有这个二进制数11000000110011000001011001111101
,它应该有这个十进制表示0.0736327171325684
。
有没有一种聪明的方法来弄清楚如何将二进制值解释为给定的十进制值?
一些背景
我有一个二进制文件,其中包含来自fortran的REAL*4
数据类型(我相信fortfran 77(。我从fortran语言参考中找到了这个:
REAL元素有一个符号位、一个8位指数和一个23位分数。f77中的这些REAL元素符合IEEE标准。
不过,在尝试应用IEEE标准时,我得到了这个十进制值-6.37774515152
,这是不正确的。我一直在尝试使用大/小endian和64位。我还尝试了二进制数据中的每个偏移量,以确保我没有看错地方,但运气不好(我能得到的最接近的仍然是0.011872760951519054
,我相信这会比精度误差大得多(。
更新:如果不清楚的话,我很抱歉:我没有生成二进制文件的原始fortran代码。
一些可能有用的额外信息:
- 这个代码大约有20年的历史了
- 从同一项目的代码中,我发现提到了IEEE和微软二进制格式之间的转换
- 我还发现提到了REAL*4,根据语言参考,它应该是REAL的别名
- 我已经成功地解码了同一文件中的类型INTEGER和INTEGER2。INTEGER类型是一个8位整数。INTEGER2类型是一个具有小端序的16位整数。这是否暗示REAL*4也是小端序
- 正如评论中所指出的,上面链接的引用是针对fortran的编译器,我们不能确定生成二进制文件的代码是否使用了相同的编译器。因此,REAL*4型可能根本没有使用IEEE标准
这是逆向工程中的一个很好的练习。看起来你的数字是小端序的,它以所谓的Microsoft二进制格式存储。根据维基百科的说法,这种格式首先存储8位指数,偏差为128;然后是1位符号,然后是23位有效位,隐含1。如果指数为0,则数字本身表示0。假设二进制点在整个有效位之前。此格式不具有表示无穷大或NaN值的,也不支持子规范。
让我们按照这个描述。您的输入是
11000000110011000001011001111101
十六进制为:
C0 CC 16 7D
从little-endian转换,比特模式为:
7D 16 CC C0
回到二进制,并以8-1-23的形式排列,我们得到:
01111101 0 00101101100110011000000
存储的指数的值为0b01111101,十进制为125。这种格式的偏差为128;所以我们有一个指数值CCD_ 6。
符号是0
,所以它是一个正数。
有效位有一个隐含的有效位,并且假设基点在整个有效位之前。所以它是:二进制的0.100101101100110011000000
。对应于:
2^-1 + 2^-4 + 2^-6 + 2^-7 + 2^-9 + 2^-10 + 2^-13 + 2^-14 + 2^-17 + 2^-18
那么,最终值是:
2^-3 * (2^-1 + 2^-4 + 2^-6 + 2^-7 + 2^-9 + 2^-10 + 2^-13 + 2^-14 + 2^-17 + 2^-18)
其在数学上评估(即,没有任何舍入/截断(为:
0.07363271713256836
我相信这就是你最初想要的价值。