Data Lab 1(深入理解计算机系统)

记录自己的学习过程!

程序内允许使用:
a. 运算符: ! ~ & ^ | + << >>
b. 范围在0 - 255之间的常数
c. 局部变量
程序内禁止以下行为:
a. 声明和使用全局变量
b. 声明和使用定义宏
c. 声明和调用其他的函数
d. 类型的强制转换
e. 使用许可范围之外的运算符
f. 使用控制跳转语句:if else switch do while for

int is AsciiDIgit(int x)

  1. int isAsciiDigit(int x) 主要考虑int型变量溢出情况
    功能:当0x30<=x<=0x39时(即字符0-9的ASCII码值)返回1;其他情况下返回0
  int isAsciiDigit(int x) {
  /*判断X-0x30与0x39-X的符号位的情况,同时也排除了int溢出的影响*/
  int test1=x+(~(0x30)+1);
  int test2=(~x+1)+0x39;//若溢出,二者的符号位仍是不同的,可排除。
  test1=(test1>>31)+1;
  test2=(test2>>31)+1;//算数右移31bit,符号位填满。+1后只有0,1两种情况。

  return test1&test2;//符号要求情况应该为二者都为1即1&1;其余情况均为0
}

int anyEvenBit(int x)

  1. int anyEvenBit(int x)
    功能:当x的任意偶数位为1时,返回1;其他情况下返回0
    没什么难度,主要是要知道这种方法
int anyEvenBit(int x) {
  /*对X的每个byte都进行 | 运算,只要有一个even-bit 为1,则&0x55结果不为0。 !!运算后可转换为1 */

  int test1=((x>>8)|(x>>16)|(x>>24)|x)&0x55;//even-bit 全为0时, test1=0, 否则不为0.

  return !!test1;     //将test通过!!运算转化为0或1的结果返回
}

int copyLSB(int x)

  1. int copyLSB(int x)
    功能:将返回值中的所有位全部置位成x中的第0位的值
    主要考查掩码的应用
int copyLSB(int x) {
  /*使用掩码0x01 获得x的最低位,通过左移到最高为, 进行算术右移,变为由32个符号位组成的int数据*/
  int test1=x&1;//获得least-bit;
  x=(test1<<31)>>31;//将least-bit变为符号位,再使用算术右移, 补符号位(least-bit);
  return x;
}

int leastBitPos(int x)

  1. int leastBitPos(int x)
    功能:返回⼀个掩码,在该掩码中标识了⼆进制数x的所有位中,“1”所在的位权最 小的位
    主要考虑(~x+1)和x的位级别关系
    若x=01 01 11 00,则~x=10 10 00 11,~x+1=10 10 01 00
    可以看到~x+1和x(从右往左看),在第一个‘1’出现之前位都是相同的,而‘1’之后位级别是取反的。
    所以可以用(~x+1)&x得到第一个‘1’。
int leastBitPos(int x) {
  /*~x在0~目标位为1,在目标位为0. ~x+1后0~目标位保持不变,而其他位为原值的反
  故 (~x+1)&x保留了0~目标位,而目标位~31都为0*/
  x=(~x+1)&x;
  return x;
}

int divpwr2(int x, int n)

  1. int divpwr2(int x, int n)
    功能:计算 x / 2^n,并将结果取整
    主要考虑负数的情况
int divpwr2(int x, int n) {
/*对非负数只需要>>n bit;  对于负数,需要加上2^n-1,再>>n bit;所以需要得到一个正数为0,负数为2^n-1的偏移量*/
/*为什么要加2^n-1?   1.因为对于被二整除的负数,没有影响*/
/*                   2.对不可被二整除的负数,加它后会进位,即原来得数+1,即相当于向零取整*/

    int test1=(0x01<<n)+~0x00;//获得2^n-1
    int test2=x>>31;          //让符号位占满32bit
    test1=test2&test1;      //若为负数,则偏移量为2^k-1. 若为正数,则偏移量为0
    x=(x+test1)>>n;
    return x;
}

int bitCount(int x)

  1. int bitCount(int x)
    功能:计算二进制数x中,对应位值“1”的总位数
    核心思想是将一个表示原来数字的01序列==>一个表示1的个数的01序列
int bitCount(int x) {
    /*为了统计为1的位数,我们必须把这个32-bit的数值,转化为一个统计1个数的数字*/
  int test1=(0x55<<8)|(0x55);
  test1=(test1<<16)|(test1);
  x=(x&test1)+((x>>1)&test1);//首先将每两位看成一个整体,利用掩码0101...0101计算每两位中1的个数,并存入x的对应位置
                             //例一个16-bit的数:10 11 00 11 11 00 01 10 -->> 01 10 00 10 10 00 01 01
   test1=(0x33<<8)|(0x33);
  test1=(test1<<16)|(test1);
  x=(x&test1)+((x>>2)&test1);/*再将每四位看成一个整体, 利用掩码0011...0011将每两位的1的个数变为
                               每四位的1的个数,存入x的对应位置*/
                             //0110 0010 1000 0101 -->> 0011 0010 0010 0010
   test1=(0x0f<<8)|(0x0f);
  test1=(test1<<16)|(test1);
  x=(x&test1)+((x>>4)&test1);/*再将每八位看成一个整体, 利用掩码0000 1111...0000 1111将每4位的1的个数变为
                               每8位的1的个数,存入x的对应位置*/
                             //0011 0010 0010 0010 -->> 0000 0101 0000 0100
   test1=(0xff<<16)|(0xff);
  x=(x&test1)+((x>>8)&test1);/*再将每16位看成一个整体, 利用掩码 0000 0000 1111 1111 0000 0000 1111 1111将每8位的1的个数变为
                               每16位的1的个数,存入x的对应位置*/
                             //0000 0101 0000 0100 -->> 0000 0000 0000 1001 = (9)与原数吻合
   test1=(0xff<<8)|(0xff);
  x=(x&test1)+((x>>16)&test1);/*再将这32位看成一个整体, 利用掩码 0000 0000 0000 0000 1111 1111 1111 1111将每16位的1的个数变为
                               每32位的1的个数,存入x的对应位置*/
                               //此时x的数值就变为了原x中所有1的个数
  return x;
}
  • 24
    点赞
  • 76
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值