这个min()函数如何工作?

时间:2016-10-29 11:49:12

标签: c++ c bit-manipulation

我遇到了这段代码:

int __min(int a, int b) {
    return ((a)-(((a)-(b))&((b)-(a))>>31));
}

我可以想象它与2s补码有关,它只适用于有符号的32位整数,但之后我就迷失了。

我找到this question,但我不认为这些功能是相关的,还是我错了?

所以我有两个问题:

  1. 为什么这个功能有效?
  2. 是否存在(a<b)?a:b无法正常工作的情况,这个功能会不会过于复杂?
  3. 编辑:该函数是为GPU编写的,所以我认为@Banex可能是正确的,因为这样做是为了避免分支。

2 个答案:

答案 0 :(得分:2)

这适用于32位有符号值。让我们一步一步地解决这个问题。

((b)-(a))>>31)

右移运算符基本上取32位值中的最高位,并将其符号扩展到剩余的31位。这就是右移运算符对有符号值的作用。

如果b大于a,则减法的结果为正,最高位为0,结果为0。

如果b小于a,则减法的结果为负,最高位为1,结果为-1。最高位向下移位到所有剩余位。将设置32位值中的所有位,即-1。

您可以通过编写一个将正值或负值放入32位int,将其右移31位的短程序来自行验证;然后观察结果将是0或-1。如您所知,在二进制补码算法中,值-1的所有位都已设置。

((a)-(b)) & (0 or -1, as the result of the previous operation).

因此,如果b小于a,则右侧值会设置所有位,而按位&运算符的结果是左侧值。或a-b

如果b大于a,则右侧值的所有位都为0,&的结果为0。

总结:

如果b小于a,则上述表达式的计算结果为:

a-(a-b)

or

a-a+b

or

b

如果b大于a,则表达式的结果为

a - 0

or

a

答案 1 :(得分:0)

表达式

((a)-(b))&((b)-(a))>>31

即。没有最多余的括号

(a - b) & (b - a) >> 31

评估为

a - b

如果a&gt; b,以及

0

否则,如果最终从a中减去它,则与

相同
if (a > b)
   return (a - (a - b));
else
   return (a - 0);