此问题与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个比特,并且仍然是负数(在2的补负数必须以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 >> 29)< < 29不会导致相同的数字,因为当我们将5移动到32位有符号数的末尾时,它从1开始,因此变为自己签名。
下一行是要简单得多
(x^number)
将是0,如果x ==数量,因为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,而向右移动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))
来源
2017-03-21 17:26:29
snb
谢谢!你真的帮助了我。 – HumbertZhang