计算机系统基础 实验——位运算

位操作与逻辑运算在C语言中的应用
本文详细介绍了C语言中位操作符的使用,包括取负、按位或、条件运算、字节取反、判断偶数位、字节交换、位掩码、大小比较、适合短整型、适合位数、判断最小值、溢出检查、循环左移、次幂检测以及原码到补码转换。通过实例解析了各种位操作的实现思路和步骤,展示了位运算在解决计算问题中的灵活性。

1.negate(取负)

要求:将所给数x取负。
操作:将操作数取反+1。

/* 
 * negate - return -x 
 *   Example: negate(1) = -1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 5
 *   Rating: 2
 */
int negate(int x) {
   
   
  return ~x+1;
}

2.bitOr(两数相或)

要求:只利用 ~ 和 & 操作,将数 x 和 y 相或。
操作
取或,等价于将两个数的取反值~x, ~y相与后,再取反。

/* 
 * bitOr - x|y using only ~ and & 
 *   Example: bitOr(6, 5) = 7
 *   Legal ops: ~ &
 *   Max ops: 8
 *   Rating: 1
 */
int bitOr(int x, int y) {
   
   
  return ~(~x&~y);
}

3.conditional(选择运算符)

要求:用逻辑运算实现三目运算:x ? y : z
思路
构造一个数 f,方便选择输出。
f = ~(!x) + 1; 当x为0时,f 的每一位全为1;当x不为0时,f 的每一位全为0

  • 取1的反(11111..110) +1 后,所有位都为1;
  • 取0的反(11111..111) +1 后,所有位都为0(溢出)。

之后选择输出y或z:return (z & f) + (y & ~f);

int conditional(int x, int y, int z) {
   
   
	int f = ~(!x)+1; //x为0,f每位全为1;x不为0,f每位全为0。 
	return (y & ~f) + (z & f); 
}

4.byteNot(对某个字节取反)

要求:将所给数 x 的第 n 个字节取反。
思路
取反可以用数位为1的数进行异或(^)操作,因为:

  • 原来数位为1,和1取异或后变为0;
  • 原来数位为0,和1取异或后变为1。

所以可以构造只有当前字节所在数位为1,其他位为0的数,和所给数相异或
一个字节占 8 个数位。
第 n 个字节,需要将数 0xff (11111111 = 255) 左移 8*n 个数位。
但是不能用乘法,所以可以将 8 表示为 2^3,构造数 y 为:y = n << 3
之后和 x 相异或,就把第n个字节取反了。

/* 
 * byteNot - bit-inversion to byte n from word x  
 *   Bytes numbered from 0 (LSB) to 3 (MSB)
 *   Examples: getByteNot(0x12345678,1) = 0x1234A978
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 6
 *   Rating: 2
 */
int byteNot(int x, int n) {
   
   
	int t = 0xff; //255:11111111 
	t <<= n<<3; //左移n*8位,变为00000..0011111111000..00 
	return x ^ t;
}

经验: 取反操作,异或上1。


5.allEvenBits

要求:判断数x的偶数数位是否都为1。
思路

方法1
int类型的数,偶数都为1,便是:01010101…0101。
所以先将数x的奇数数位全部变为0,然后判断其是否和上面的数相等就行了。

如何将数x的奇数数位全部变为0,偶数数位不变?
构造奇数数位全为0,偶数数位全为1的数y,和数x相与。

如何判断数x是否为 01010101…0101?
构造出该数,和数x相异或,看结果是否为0。若为0,则完全一致。

如何构造出奇数数位全为0,偶数数位全为1的数(01010101…0101)?
先构造出8位,再进行左移操作后相或。

int y=0x55;  y |= y<<8;  y |= y<<16;

方法2
构造奇数数位全为1,偶数数位全为0的数(10101010…1010),判断其和数 x 相或后是否所有数位全为1。如果是,则说明数 x 的偶数数位全为1。

如何判断是否一个数位全为1呢?
取反看其是否为0。或者直接判断其是否为11111(取^操作)

/* 
 * allEvenBits - return 1 if all even-numbered bits in word set to 1
 *   Examples allEvenBits(0xFFFFFFFE) = 0, allEvenBits(0x55555555) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 12
 *   Rating: 2
 */
int allEvenBits(int x) {
   
   
	//方法1:
	int y=0x55;
	y |= y<<8;
	y |= y<<16; //构造32位偶数位置全为1,奇数位置全为0的数:0101 0101... 
	x &= y; //先将x的奇数位上的值全部变为0 
	
	return !(x^y); //如果x
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值