我在写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!
答案 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) )