c++ - 这段获取最低位位置的代码是如何工作的?

标签 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++ 编程以来已经有一段时间了,如果可能的话,我正在尝试为可编程逻辑 Controller (PLC) 编写逻辑来执行相同的操作。

感谢您的帮助

最佳答案

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

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

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

value = 010100100
d     = 000000111

发生这种情况是因为 (value - 1)value 相同,只不过最低的零位串变为 1,而下一位变为 0,由于携带

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

无论如何,d 都会加载 this 的浮点值。下一行:

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

这会提取浮点指数,并加回偏差。请注意,这假设是小端系统,例如 x86;在大端系统上,您需要使用[0]。它还对 intdouble 的大小做出假设 - 特别是,它假设 32 位 int 和 64 位 IEEE float double 。

这里的关键是非非规范化的 IEEE 浮点值(并且 double 型中的 32 位 int 始终是非非规范化的)最终的表示形式看起来有点像 1.xxxxxxx * 2^ (e-1023),其中 xxxxxxxx 是小数部分,e 是指数。由于您已将感兴趣的位安排为最高阶位,因此指数与您要查找的值成正比。

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

关于c++ - 这段获取最低位位置的代码是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4766397/

相关文章:

mysql - MySQL 中 double 和 float 数据类型的最大精度是多少

python - 将 C bitfiddling 移植到 Python 的惯用方法

c++ - 按位替换两个数字中的位

c++ - 用新的函数声明语法覆盖

c++ - 警告 : section "__textcoal_nt" is deprecate since updating to Mac OSX Sierra

c++ - 多次 fork 后无法向父进程发送消息

c - matlab和c的cos函数不同

c++ - 为什么虚函数会出现段错误

c++ - 生成下一个最大或最小的可表示 float ,无需位旋转

c++ - 使用位的标志