按位运算:FitsBits

时间:2017-03-14 15:42:18

标签: bitwise-operators

我在写FitsBits很长一段时间遇到了一些问题,所以我用Google搜索,找到适合测试程序的解决方案,但我无法弄清楚这意味着什么。

问题描述:

  

fitsBits - 如果x可以表示为n位,则返回1,   二进制补码整数   1< = n< = 32
  例子:

     

fitsBits(5,3)= 0,fitsBits(-4,3)= 1
  法律操作:! 〜& ^ | +<< >>   Max ops:15

正确的解决方案是:

int fitsBits(int x, int n)
{   
int move;  
move = 32 +(~n+1);
return !(x^((x<<move)>>move)); 
}

但我不知道

!(x ^((&lt;&lt;&lt;&lt; move)&gt;&gt; move))

意味着什么。

我真的需要一些帮助.Thx!

1 个答案:

答案 0 :(得分:2)

此问题与Bitwise operations and shifts重复,用户要求了解相同的代码。不幸的是,我没有声名鹊起。

重申Code-Apprentice's回答和AnT's,根据您找到的解决方案进行一些修改,并对我自己的解释进行更多解释

move = 32 +(~n+1);

这实际上是32(n的最大值和此问题中的整数大小)和n之间的差异。

理解为什么要查看二进制补码有符号整数。在这种格式中,您将无符号整数(例如在原始示例中,5(0101))转换为-5,通过反转位并添加一个,

~5 + 1 = -5

~(0101) + 1 = 1011

注意1011如何不能适合3位且仍为负数(2s补码中的负数必须以1开头)

所以

move = 32 +(~n+1);

实际上是

move = 32 - n;

最后一行实际上是一行中的几个想法

!(x^((x<<move)>>move)); 

让我们分解它。

invert the truthiness of 
    (x xor a number) 
        where the number is x first shifted left then right amount move
            and move is the difference between n and 32. 

让我们再次使用5和3的例子。我们知道移动应该是32 -3,所以移动是29.

但为什么左右移动相同的数量?通常,当您看到某人在代码中执行此操作时,他们会尝试将数字“清零”。在这种情况下,作者没有这样做,而是签署扩展。看下面

例如:

given 0000 0000 0000 0000 0000 0000 0000 0101 = 5
5 << 29 = 1010 0000 0000 0000 0000 0000 0000 0000 = -1610612736
-1610612736 >> 29 = 1111 1111 1111 1111 1111 1111 1111 1101 = -3

作者正在使用rshift的实现级别怪癖,如果数字以有符号开头,它会保留其符号并在其移位时填充数字的其余部分。

注意因为符号填充(5>&gt;&gt; 29)&lt;&lt; 29不会产生相同的数字,因为当我们将5移到32位有符号数的末尾时,它从1开始,因此自身被签名。

下一行更简单

(x ^ number)
如果x == number,则

将为0,因为0 xor 1 = 1,1 xor 1 = 0,0 xor 0 = 0.因此,通过该逻辑,当我们反转x的真值时,我们正在检查是否

x == (sign shifted x)  

如果5代表8代替(1000)我们只会丢失最后一位数字(1)而我们会发现

!(8 ^ 0) == false.

如果我们选择使用一个实际工作的数字(比如3),因为3 = 011,并且将3乘29右移将导致第一位为0,我们将在来回移动时保留3的值,所以我们会找到

!(3 ^ 3) == true;

总结一下这个功能实际上只是做了以下

given int x and int n,
check if x == (x shifted left then sign shifted right by (size of int in bits - n) )