CSAPP 第二章家庭作业2.70

/* 
 * 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

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值