/*
* fitsBits - return 1 if x can be represented as an
* n-bit, two's complement integer.0 otherwise
* Assume 1 <= n <= w
*/
int fitsBits(int x, int n) {
int r, c;
c = 33 + ~n;
r = !(((x << c)>>c)^x);
return r;
}
这题真看不懂主要是因为an n-bit, two's complement integer
,真不知道什么意思…
查了一下,其实就是n个位,用补码解释能够表示的范围大小,以 n = 4 为例
A 4-bit two’s complement number also represents 16 values: −8 to 7
位向量表示:-8 -> [1000] | 7 -> [0111]
以n = 3为例。
x = 3 -> [011] -> 3
x = -4 -> [100] -> -4
x = 5 -> [101] -> -3 (最高位为符号位,无法表示)
扩展到8位
x = 3 -> [0000 0011] -> 3
x = -4 -> [1111 1100] -> -4
x = 5 -> [0000 0101] -> 5
表示这些数字最小需要的位
x = 3 -> [011] -> 3
x = -4 -> [100] -> -4
x = 5 -> [0101] -> 5
也就是需要判断 n - 1 位 是不是符号位。
第一种方式 (x<<w - n) >> w - n
以上面的例子得到
[0000 0011] -> 3
[1111 1100] -> -4
[1111 1101] -> -3 (因为5的最低符号位并不在n - 1位)
综上,只要进行移位以后再判断是否跟原数相同即可。
再来看答案
int fitsBits(int x, int n) {
int r, c;
c = 33 + ~n;
r = !(((x << c)>>c)^x);
return r;
}
c = 33 + ~n
# 分解成
c = 32 + (~n + 1)
取反+1的操作很容易想到得到补码的负数,如n = 3 (8 位表示)
3 => [0000 0011]
(~3) + 1 => [1111 1101] => -3
其实这个操作相当于
c = 33 + ~n => c = 32 - n
之前说过进行移位运算
(x<<w - n) >> w - n 这里w = 32
再看这一行
r = !(((x << c)>>c)^x);
我们经常用!(x ^ y) 判断两数是否相等,相等返回1,不相等返回0
!(0 ^ 0) //=> 1
!(1 ^ 0) //=> 0
实际上就是判断经过移位的数是否跟原来的数相等,从而判断符号位的位置。
另一种思路
扩展到8位
x = 3 -> [0000 0011] -> 3
x = -4 -> [1111 1100] -> -4
x = 5 -> [0000 0101] -> 5
扩展以后高w - n + 1位,要么为0,要么为-1
右移两位,>> n - 1
x = 3 -> [0000 0000] -> 0
x = -4 -> [1111 1111] ->-1
x = 5 -> [0000 0001] -> 1
如果右移结果为0/-1就返回1,其他返回0
int fits_bits(int x, int n){
x >>= (n-1);
return !(x ^ 0) || !(x ^ -1);
}
or
int fits_bits(int x, int n){
x >>= (n-1);
return !x || !(~x);
}
参考文章:
https://blog.csdn.net/zhanyu1990/article/details/24936663
https://stackoverflow.com/questions/42790409/bitwise-operation-fitsbits