在this文章中使用的方程我不明白:
I 是解释为整数的float的字节表示。 这是一个例子:
struct.unpack('8sii', f.read(16))
现在我的问题是:
为什么方程式是正确的,哪里可以阅读更多有关此等式的内容?
答案 0 :(得分:1)
浮点数用符号 s ,指数 e 和有效数 f 表示。 (有些人使用术语“尾数”,但这是对数纸表的遗留物。对于浮点值的小数部分,“有意义”是优选的.Mantissas是对数的。有效数是线性的。)在二进制浮点数,表示的值为+ 2 e • f 或 - 2 e < / sup>• f ,根据符号 s 。
通常对于二进制浮点,有效数必须在[1,2]中,至少对于格式的正常范围中的数字。对于编码,第一位与其余位分开,因此我们可以写 f = 1 + r ,其中0≤ r &lt; 1。
在IEEE 754基本二进制格式中,浮点数被编码为符号位,一些指数位和有效位字段:
符号 s 编码为0位为正,1为负。由于我们采用对数,因此数字可能是正数,我们可能会忽略符号位以用于当前目的。
指数位是实际指数加上一些偏差 B 。 (对于32位格式, B 为127.对于64位,为1023。)
signifcand字段包含 r 的位。由于 r 是一个分数,因此有效数字段包含以“二进制点”之后的二进制表示的 r 位。例如,如果 r 是5/16,二进制是“.0101000 ...”,因此有效数字段包含0101000 ...(对于32位格式,有效数字字段包含23位。对于64位,52位。)
设 b 有效数字段(23或52)中的位数。设 L 为2 b 。
然后 r 和 L , r • L 的乘积是一个等于内容的整数有效数字域。在我们的示例中, r 是5/16, L 是2 23 = 8,388,608, r • L = 2,621,440。因此有效数包含2,621,440,即0x280000。
等式 I =( e + B )• L + m • L 尝试捕获此内容。首先,符号被忽略,因为它是零。然后 e + B 是指数加偏差。乘以 L 将其移位 b 位,将其置于浮点编码的指数字段的位置。然后添加 r • L 添加有效数字段的值(我将 r 用于“其余有效数字”而不是 m 表示“尾数”)。
因此,当将2 e •(1+ r )编码为浮点数时,将其解释为二进制整数,( e + B )• L + r • L 。
有关IEEE 754的信息位于Wikipedia和the IEEE 754 standard。以前的一些Stack Overflow答案描述了here和here的编码格式。
关于你问题中的代码:
float x = 3.5f;
unsigned int i = *((unsigned int *)&x);
不要使用此代码,因为它的行为不是由C或C ++标准定义的。
在C中,使用:
#include <string.h>
...
unsigned int i; memcpy(&i, &x, sizeof i);
或:
unsigned int i = (union { float f; unsigned u; }) { x } .u;
在C ++中,使用:
#include <cstring>
...
unsigned int i; std::memcpy(&i, &x, sizeof i);
这些方法被定义为将浮点编码的位重新解释为unsigned int
。 (当然,它们要求在您使用的C或C ++实现中float
和unsigned int
的大小相同。)
答案 1 :(得分:0)
如您所知,浮点数存储在IEEE 754标准中。和单精度浮点的位模式如下(见详情here):
根据以下公式计算数字的值:
因此,对于32位值,等效整数将为e * L + m
。
因为指数是从(第23位)开始,第一部分是m
。
假设指数与-127
一起存储,表达式将转换为(e + B)*L + m
。
关于L
之后的m
可能会有一个假设,可能在文章中没有提及。
此外,此公式中未考虑sign
位。