【问题标题】:IEEE 754 Float debug - from memory little endian to the actual floating numberIEEE 754 浮点调试 - 从内存小端到实际浮点数
【发布时间】:2011-08-08 15:39:03
【问题描述】:

我正在使用下面的示例使用 VS2008 测试 IEEE 754 浮动格式:

int main(int argc, char *argv[])
{
    float i = 0.15625;
}

我把 &i 放到 VS2008 手表上,我看到地址是 0x0012FF60,我可以从内存调试窗口看到地址的内容是 00 00 20 3e,见下图:

0x0012FF60 00 00 20 3e cc cc cc cc

顺便说一句,我有 IEEE754 浮点格式的基本知识,我知道 IEEE 754 浮点格式由三个字段组成:符号位、指数和分数。分数是没有最高有效位的有效数字。

但是我是如何从 little endian 00 00 20 3e 精确计算到 0.15625 的呢?

非常感谢

【问题讨论】:

  • 感谢大家的意见,现在真的很清楚了,为大家打勾!

标签: c++ visual-studio-2008 ieee-754


【解决方案1】:

大端机器上 32 位浮点数的内存布局(参见 http://en.wikipedia.org/wiki/Single_precision)。

小端机器(例如 x86)只是交换字节对,“cc”是未使用的内存位,以使 32 位浮动到调试器显示的 64 位值

编辑: 记住指数是有符号的(二进制补码),因为 0.15625 小于 1,所以指数是负数)

值 = 符号 * 2^exp * 尾数。

0x3e = 0011 1110
0x20 = 0010 0000

由于符号位,我们必须将它们随机排列,所以
指数 = 0111 1100 = -3
尾数 = 0100 0000 = 1 + 0.25(假定为第一名之前的那个)

即 0.15625 = +1 * 2^(-3) * 1.25

【讨论】:

  • 这张图片的位顺序是什么?它读作 7C 40,即使是相反的顺序(假设它是大端?),它是 02 3e,而不是 20 3e。我在这里遗漏了一些明显的东西吗?
  • 我怀疑“交换字节对”,这不是 OP 机器上发生的事情。
  • 另外,指数不是“有符号的”,而是“有偏差的”!
  • 指数是用数学签名的,它只是在存储中存在偏差
【解决方案2】:

您正在打印一些损坏的东西。我们只需要 32 位,分别是:

00 00 20 3E

你的二进制变量:

00000000 00000000 00100000 00111110

逻辑值占小端:

00111110 00100000 00000000 00000000

根据 IEEE:

0 01111100 01000000000000000000000
S E - 127  M - 1

所以现在很清楚了:

  • 符号是 +1 (S = 0)
  • 指数为 124 - 127 = -3
  • 尾数为 1.01b,即 5/4

所以该值为 5/4 / 8 = 5/32 = 0.15625。

【讨论】:

  • 这不是打印,是我从VS2008内存调试窗口复制的
【解决方案3】:

您的值是十六进制 0x3E200000 或

0011 1110 0010 0000 0000 0000 0000 0000 

或重新排列:

s ----e--- ----------m------------
0 01111100 01000000000000000000000

sign_bit    = 0 (i.e. positive)
exponent    = 0x7C = 124 ---> subtract 127 to get -3
significand = 1 + 0.0100... = 1.0100... = 1*2^0 + 0*2^-1 + 1*2^-2 = 1.25

significand * 2^exponent = 1.25 * 2^-3 = 1.25 * 0.125 = 0.15625

【讨论】:

  • 为什么是-4?为什么符号是“零”?
  • 符号 bit 为零。 -4 是一个错字并已更正。将符号重命名为 sign_bit。
【解决方案4】:

IEEE 浮点的基本格式是基于一个四字节 值,如果这样显示它更容易分析。在那里面 在这种情况下,最高位是指数,接下来的 8 位是指数(超过 127),其余的是尾数。最简单的解释方法是 可能会显示将访问单独字段的 C++ 代码:

double d;
// ...
uint32_t const* p = reinterpret_cast<uint32_t const*>( &d );
bool isNegative = (*p & 0x80000000) != 0;
int exp = ((*p & 0x78000000) >> 23) - 127;
int mantissa = (*p & 0x07FFFFFF) | 0x08000000 ;

尾数应在 24 位上方有一个隐含的小数位 位(但我不知道如何将其表示为整数:-))。

如果你只有一个字节序列,你必须组装它们, 按照字节顺序,然后应用上面的。

已编辑:常量值已更正,跟进 Rudy Velthuis 指出我的错误。

【讨论】:

  • 那是int exp = ((*p &amp; 0x78000000) &gt;&gt; 23) - 127; 和 isNegative 一样。
  • @Rudy 是的。我不知道我在想什么。很久以前,我在 16 位机器上做了很多工作,但我从未见过 16 位浮点格式:-) 我会编辑它(所有十六进制值都会受到影响)---感谢更正.
猜你喜欢
  • 1970-01-01
  • 2012-01-06
  • 2014-10-18
  • 2013-07-24
  • 1970-01-01
  • 2017-04-08
  • 1970-01-01
  • 1970-01-01
  • 2023-03-08
相关资源
最近更新 更多