有没有办法找到使用哪种浮点运算
Posted
技术标签:
【中文标题】有没有办法找到使用哪种浮点运算【英文标题】:Is there a way to find what kind of Floating-point arithmetic is used 【发布时间】:2021-08-08 07:06:04 【问题描述】:我有这个二进制数11000000110011000001011001111101
,它应该有这个十进制表示0.0736327171325684
。
有没有一种聪明的方法来弄清楚如何将二进制值解释为给定的十进制值?
一些背景
我有一个二进制文件,其中包含来自 fortran 的 REAL*4
数据类型(我相信是 fortfran 77)。
我是从fortran language reference 找到的:
REAL 元素有一个符号位、一个 8 位指数和一个 23 位小数。 f77 中的这些 REAL 元素符合 IEEE 标准。
但是,尝试应用 IEEE 标准时,我得到了这个十进制值 -6.37774515152
,这是不正确的。我一直在试验大/小端和 64 位。我还尝试了二进制数据中的每个偏移量,以确保我没有看错地方,但没有运气(我能得到的最接近的仍然是0.011872760951519054
,我相信它会比精度错误大得多)。
更新:如果不清楚,我很抱歉:我没有生成二进制文件的原始 fortran 代码。
一些可能有用的额外信息:
代码大约有 20 年的历史。 从同一个项目的代码中,我发现提到了 IEEE 和 microsoft 二进制格式之间的转换。 我还发现提到 REAL*4,根据语言参考,它应该是 REAL 的别名。 我已经成功地从同一个文件中解码了 INTEGER 和 INTEGER2 类型。 INTEGER 类型是一个 8 位整数。 INTEGER2 类型是一个小端序的 16 位整数。这是否暗示 REAL*4 也是小端序? 正如 cmets 中所指出的,上面链接的参考是针对 fortran 编译器的,我们无法确定生成二进制文件的代码是否使用了相同的编译器。因此,REAL*4 类型可能根本没有使用 IEEE 标准。【问题讨论】:
嗯,需要一些重要的细节。是大端还是小端?还有文件是如何创建的(即直接访问或流访问)?这很重要,因为您可能有可能使读取文件变得复杂的记录标记。数字0.0736327171325684
对于单精度数字来说数字太多。后面的 6 或 7 位数字可能是垃圾。您是否将 REAL*4
(注意,无效的 Fortran 类型,但我离题)变量设置为 0.073....
并以 B32.32
格式打印值?内容丰富。
您的“语言参考”仅是 Oracle 针对特定编译器的参考。请注意,根据数据的年龄,一些未知数据可能来自 Fortran 编译器使用不同浮点格式的旧计算机。 Fortran 标准并不要求使用 IEEE 标准,尽管它在本世纪非常普遍。
Fortran 语言没有提及 REAL*4
或默认实类型具有什么 IEEE-754 合规性。您链接的文档是指一个编译器的实现:如果您没有在该系统上使用该编译器,那么它所说的没有用。请向我们详细说明 Fortran 用于生成您获得的数据(在此之前,我不认为这是 Fortran 问题,因此删除了标签)。
@VladimirF 感谢您对编译器的见解。考虑到我没有用 IEEE-754 测试蛮力强制整个文件,我相信这可能就是这种情况。我用一些额外的信息更新了帖子。
@steve 我不知道它是大端还是小端,但我在同一个文件中发现了小端的其他值,用该信息更新了帖子。我不知道文件是如何创建的。由于我不知道使用了哪种 fortran 编译器,因此无法将十进制值转换为与原始生成文件格式相同的二进制值。
【参考方案1】:
这是逆向工程中的一个相当大的练习。您的号码似乎是小端格式,并且以所谓的 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)
以数学方式计算(即,没有任何舍入/截断):
0.07363271713256836
我相信这就是您最初寻找的价值。
【讨论】:
非常感谢!这非常有效。以上是关于有没有办法找到使用哪种浮点运算的主要内容,如果未能解决你的问题,请参考以下文章