获取最低位位置的代码如何工作?

时间:2011-01-22 05:45:21

标签: c++ floating-point bit-manipulation

unsigned GetLowestBitPos(unsigned value)
{
   double d = value ^ (value - !!value); 
   return (((int*)&d)[1]>>20)-1023; // This is what I really need help understanding. 
}

在我看来,代码将一个double转换为指向整数的指针。我不确定[1]的用途是什么。然后看起来我们正在向右移位20位

感谢您对此代码的任何帮助。 我已经用C ++编程了一段时间,我正在尝试为可编程逻辑控制器(PLC)编写逻辑,以便在可能的情况下做同样的事情。

感谢您的帮助

1 个答案:

答案 0 :(得分:6)

让我们一步一步走。第一:

double d = value ^ (value - !!value);

如果value = 0,则计算结果为0 ^(0 - 0),因此d为0。 如果value != 0,则计算结果为^(value - 1)。这具有将最低的一位和最低的零位设置为一,并将所有其他位设置为零的效果。例如:

value = 010100100
d     = 000000111

这是因为(value - 1)value相同,只是最低的0位字符串变为1,而下一位变为零,由于携带

value     = 010100100
value - 1 = 010100011
XOR value = 000000111

在任何情况下,d都会加载浮点值。下一行:

return (((int*)&d)[1]>>20)-1023; 

这提取浮点指数,并加回偏差。请注意,这假设有一个小端系统,例如x86;在大端系统上,您需要使用[0]。它还假设intdoubles的大小 - 特别是它假设32位整数,64位IEEE浮点数用于双精度。

这里的关键是非非规范化的IEEE浮点值(以及double中的32位int将始终是非非规范化的)最终得到的表示看起来有点像1.xxxxxxxx * 2^(e-1023),其中{{ 1}}是小数分量,xxxxxxxx是指数。由于你已经将那些感兴趣的位置作为最高位的位,所以exponentend和你正在寻找的值。

也就是说,你可能无法在PLC上使用它 - 尽管它是一个非常聪明的黑客,但如果你有一个硬件FPU它甚至可以远程高效;甚至在x86系统上也有faster built-in integer operationsthis SO question中有许多其他技巧;你可能会在那里找到一个更快的。您的PLC也可以在一条指令中执行内置操作。