有没有办法找到使用了哪种浮点运算
Is there a way to find what kind of Floating-point arithmetic is used
我有这个二进制数 11000000110011000001011001111101
,它应该有这个十进制表示 0.0736327171325684
。
有没有聪明的方法来弄清楚如何将二进制值解释为给定的十进制值?
一些背景
我有一个二进制文件,其中包含来自 fortran 的 REAL*4
数据类型(我相信是 fortfran 77)。
我从 fortran language reference:
中找到了这个
A REAL element has a sign bit, an 8-bit exponent, and a 23-bit fraction. These REAL elements in f77 conform to the IEEE standard.
不过,尝试应用 IEEE 标准时我得到了这个十进制值 -6.37774515152
,这是不正确的。我一直在试验 big/little-endian 和 64 位。我还尝试了我的二进制数据中的每个偏移量以确保我没有看错地方,但没有运气(我能得到的最接近的仍然是 0.011872760951519054
,我相信这比精度误差大得多).
更新:如果不清楚,我很抱歉:我没有生成二进制文件的原始 Fortran 代码。
一些可能有用的额外信息:
- 代码已有 20 年历史了。
- 在同一个项目的代码中,我发现提到了 IEEE 和 Microsoft 二进制格式之间的转换。
- 我还发现了 REAL*4 的提及,根据语言参考,它应该是 REAL 的别名。
- 我已经从同一个文件中成功解码了 INTEGER 和 INTEGER2 类型。 INTEGER 类型是一个 8 位整数。 INTEGER2 类型是一个 16 位整数,小字节序。这是否暗示 REAL*4 也是小端字节序?
- 正如评论中所指出的,上面链接的参考是针对 fortran 的编译器,我们不能确定生成二进制文件的代码使用了相同的编译器。因此,REAL*4 类型可能根本没有使用 IEEE 标准。
这是一个相当大的逆向工程练习。看来您的号码是小尾数法,并且以所谓的 Microsoft 二进制格式存储。根据wikipedia,这种格式先存储8位指数,偏置128;然后是 1 位符号,然后是 23 位有效数,隐式为 1。如果指数为 0,则数字本身表示 0。假定二进制小数点在整个有效数之前。此格式不 表示无穷大或 NaN 值,也不支持次正规。
让我们按照这个描述。您的输入是
11000000110011000001011001111101
其中,在十六进制中是:
C0 CC 16 7D
从小端转换,位模式为:
7D 16 CC C0
回到二进制,摆出8-1-23阵型,我们得到:
01111101 0 00101101100110011000000
存储的指数值为0b01111101,十进制为125。这种格式的偏差是 128;所以我们有一个指数值 -3
.
符号是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)
数学计算(即没有任何 rounding/truncation)为:
0.07363271713256836
我相信这是您首先要寻找的价值。
我有这个二进制数 11000000110011000001011001111101
,它应该有这个十进制表示 0.0736327171325684
。
有没有聪明的方法来弄清楚如何将二进制值解释为给定的十进制值?
一些背景
我有一个二进制文件,其中包含来自 fortran 的 REAL*4
数据类型(我相信是 fortfran 77)。
我从 fortran language reference:
A REAL element has a sign bit, an 8-bit exponent, and a 23-bit fraction. These REAL elements in f77 conform to the IEEE standard.
不过,尝试应用 IEEE 标准时我得到了这个十进制值 -6.37774515152
,这是不正确的。我一直在试验 big/little-endian 和 64 位。我还尝试了我的二进制数据中的每个偏移量以确保我没有看错地方,但没有运气(我能得到的最接近的仍然是 0.011872760951519054
,我相信这比精度误差大得多).
更新:如果不清楚,我很抱歉:我没有生成二进制文件的原始 Fortran 代码。
一些可能有用的额外信息:
- 代码已有 20 年历史了。
- 在同一个项目的代码中,我发现提到了 IEEE 和 Microsoft 二进制格式之间的转换。
- 我还发现了 REAL*4 的提及,根据语言参考,它应该是 REAL 的别名。
- 我已经从同一个文件中成功解码了 INTEGER 和 INTEGER2 类型。 INTEGER 类型是一个 8 位整数。 INTEGER2 类型是一个 16 位整数,小字节序。这是否暗示 REAL*4 也是小端字节序?
- 正如评论中所指出的,上面链接的参考是针对 fortran 的编译器,我们不能确定生成二进制文件的代码使用了相同的编译器。因此,REAL*4 类型可能根本没有使用 IEEE 标准。
这是一个相当大的逆向工程练习。看来您的号码是小尾数法,并且以所谓的 Microsoft 二进制格式存储。根据wikipedia,这种格式先存储8位指数,偏置128;然后是 1 位符号,然后是 23 位有效数,隐式为 1。如果指数为 0,则数字本身表示 0。假定二进制小数点在整个有效数之前。此格式不 表示无穷大或 NaN 值,也不支持次正规。
让我们按照这个描述。您的输入是
11000000110011000001011001111101
其中,在十六进制中是:
C0 CC 16 7D
从小端转换,位模式为:
7D 16 CC C0
回到二进制,摆出8-1-23阵型,我们得到:
01111101 0 00101101100110011000000
存储的指数值为0b01111101,十进制为125。这种格式的偏差是 128;所以我们有一个指数值 -3
.
符号是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)
数学计算(即没有任何 rounding/truncation)为:
0.07363271713256836
我相信这是您首先要寻找的价值。