位运算练习作业

该博客旨在让读者进一步理解《信息的表示和处理》内容,掌握整数、浮点数表示和运算方法及GNU GCC工具集使用。要求补全bits.c中的6个函数,如isAsciiDigit、anyEvenBit等,并给出各函数功能、示例、难度和可使用运算符数,同时说明了程序允许和禁止的行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

进一步理解书中第二章《信息的表示和处理》部分的内容,深刻理解整数、浮点数的表示
和运算方法,掌握GNU GCC工具集的基本使用方法。

要求

请按照要求补全 bits.c 中的函数,并进行验证。包括以下6个函数 :

1. int isAsciiDigit(int x)

功能:当0x30<=x<=0x39时(即字符0-9的ASCII码值)返回1;其他情况下返回0
示例:isAsciiDigit(0x35) = 1
isAsciiDigit(0x3a) = 0
isAsciiDigit(0x05) = 0
难度:3
可使用运算符数:15

int isAsciiDigit(int x) {
  int up_num = x + (~58 + 1);  //最高位为1
  int low_num = x + (~48 + 1);   //最高位是0
  
  int Is_up_legal = (!((up_num >> 31) + 1));
  int Is_down_legal = ((low_num >> 31) + 1);
  
  return   (Is_up_legal & Is_down_legal);
}
  In this function, what we should to do is to judge weather the 'x' is bigger than 48(inclusive) and smaller than 57(inclusive). 
  first:
  we mapping the legal-x:
  up_num = x -58;     
  low_num = x - 48;
  we will get (up_num < 0) and (low_num >= 0) if the "x" is legal.
  then:
  "(( up_num >> 31) + 1)" will be equal to 0 ,if (up_num < 0).
  "((low_num >> 31) + 1)" will be equal to 1 ,if (low_num >= 0).
  so,if (up_num < 0), "Is_up_legal" will be equal to 1.if (low_num >= 0),"Is_down_legal" will be equal to 1.
  last:
  only if ((up_num >> 31) + 1) == 0 and ((low_num >> 31) + 1), we return 1;

2. int anyEvenBit(int x)

功能:当x的任意偶数位为1时,返回1;其他情况下返回0
示例:anyEvenBit(0xA) = 0
anyEvenBit(0xE) = 1
难度:2
可使用运算符数:12

int anyEvenBit(int x) {
  int x1 = x >> 8;
  int x2 = x1 >> 8;
  int x3 = x2 >> 8;
  return !!( ( x | x1 | x2 | x3 )& 0x55);
}
  /*
  每次我们移动8位,把移动的3次结果和x一起做|运算,相当于把每8个信息都重叠到最低的8位,
  此时与01010101做&运算就可以知道其偶数位是否是1.
  */

3. int copyLSB(int x)

功能:将返回值中的所有位全部置位成x中的第0位的值
示例:copyLSB(5) = 0xFFFFFFFF, copyLSB(6) = 0x00000000
难度:2
可使用运算符数:5

int copyLSB(int x) {
  int temp = x & 1;
  return (~temp + 1);
}

  /*
  first, we could get least significant bit by used "x & 1".
  then, we could get result 
  */

4. int leastBitPos(int x)

功能:返回一个掩码,在该掩码中标识了二进制数x的所有位中,“1”所在的位权最小的位
示例:leastBitPos(0x60) = 0x20
难度:2
可使用运算符数:6

int leastBitPos(int x) {

  return (~x+1) & x;
}
  /*
  we get the "-x",than "(-x)&x" is what we need.
  */

5. int divpwr2(int x, int n)

功能:计算 x / 2^n,并将结果取整
示例:divpwr2(15,1) = 7
divpwr2(-33,4) = -2
难度:2
可使用运算符数:15

int divpwr2(int x, int n) {
  int op = (x >> 31) + 1;
  int temp  =   x  >> n;
  int temp2 = temp << n;
  int Is_exact_division = !!(temp2 ^ x);
  return (temp + (    (!op) & (!!n) & (Is_exact_division)  )   );
}
  /*
  一般来说,“>>”符号代表 x/(2^n),并向下取整(无论正负)。
  所以有三种情况需要考虑:
    如果负数,需要向上取整。
    如果 n=0 应该为 x。
    如果能够整除,就不需要取整操作。

  此题中,op是符号标志位,正数为1,负数为0.
  temp为x右移动n位结果,相当直接 x/(2^n) ,向下取整。
  temp2为temp左移动n位结果,利用(temp2 ^ x),可以判断temp舍弃的几位是否都是0(既能否整除)。
  Is_exact_division 代表如果能整除为0,反之为1。
  因为>>默认代表向下取整,所以我们需要考虑上述情况,利用 (!op) & (!!n) & (Is_exact_division)实现,
  其含义:同时满足 (负数)(n!=0)(不能整除) 三种情况返回1,否则返回0。
  也意味着,满足上述三情况才需要在向下取整的前提+1,否则向下取整结果就是正常取整结果。
  */

6. int bitCount(int x)

功能:计算二进制数x中,对应位值“1”的总位数
示例:bitCount(5) = 2
bitCount(7) = 3
难度:4
可使用运算符数:40

int bitCount(int x) {

  int mask = (0x11 <<24) | (0x11 << 16) | (0x11 << 8) |(0x11) ;

  int temp = x & mask;
  x = x >> 1;
  temp = temp + (x & mask); 
  x = x >> 1;
  temp = temp + (x & mask); 
  x = x >> 1;
  temp = temp + (x & mask); 
  
  return ((temp & 0xf) + 
          ( (temp >> 4) & 0xf )+ 
          ( (temp >> 8) & 0xf )+
          ( (temp >> 12) & 0xf )+
          ( (temp >> 16) & 0xf )+
          ( (temp >> 20) & 0xf )+
          ( (temp >> 24) & 0xf )+
          ( (temp >> 28) & 0xf ));

}
 /*首先分割成4块,每块右移动,同时比较每个块的1的个数*/

tip:程序内允许使用:

a. 运算符: ! ~ & ^ | + << >>
b. 范围在0 - 255之间的常数
c. 局部变量

tip:程序内禁止以下行为:

a. 声明和使用全局变量
b. 声明和使用定义宏
c. 声明和调用其他的函数
d. 类型的强制转换
e. 使用许可范围之外的运算符
f . 使用控制跳转语句:if else switch do while for
注意:违背以上原则均视为程序不正确!!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值