实验 1 :Data Lab

bitXor(x, y)

使用 ~ 和 & 实现异或操作,返回 x ⊕ y x \oplus y xy

int bitXor(int x, int y) {
    return ~(~x & ~y) & ~(x & y);
}

根据异或的运算规则,我们只需要将不同时为 0 0 0 的位和不同时为 1 1 1 做与操作。

tmin()

返回最小的整数补码

int tmin(void) {
    return 1 << 31;
}

补码带有符号位,最小的整数补码只有符号位为 1 1 1 ,其他位为 0 0 0

isTmax(x)

x x x 为最大的整数补码时返回 1 1 1 ,否则返回 0 0 0

int isTmax(int x) {
    int tmin = x + 1;
    x = x + tmin;
    x = ~x;
    tmin = !tmin;
    x = x + tmin;
    return !x;
}

最大的整数补码为 011111…,因此我们的目的就是将 x x x 变为 0 0 0 。不妨假设 x x x 为最大整数补码。第一步加 1 1 1 后就变成了 T m i n T_{min} Tmin ,此时 x + T m i n x + T_{min} x+Tmin 就等于 − 1 -1 1 ,取反后就变成了 0 0 0

但是还有一种特殊情况,当 x = − 1 x=-1 x=1 时,仍然可以通过前面的步骤来变成 0 0 0,所以我们就要对这种情况进行额外判断,此时 t m i n tmin tmin 的值为 0 0 0 ,进行非操作后就变成了 1 1 1 ,与 x x x 相加后就不等于 0 0 0 ,可以排除这种情况。

allOddBits(x)

x x x的奇数位都为 1 1 1时返回 1 1 1,否则返回 0 0 0

int allOddBits(int x) {
    int c = 0x55;
    c = c + (c << 8);
    c = c + (c << 16);
    return !((x & (~c)) ^ (~c));
}

首先将数字变成 0x55555555 的形式,取反后为 0xAAAAAAAA ,如果 x x x 的奇数位都为 1 1 1 ,那么与 0xAAAAAAAA 与操作后仍为 0xAAAAAAAA,通过异或进行判断。

negate(x)

返回 − x -x x

int negate(int x) {
    return ~x + 1;
}

isAsciDigit(x)

48 ≤ x ≤ 57 48 \le x \le 57 48x57 时返回 1 1 1 , 否则返回 0 0 0

int isAsciiDigit(int x) {
    int a = !(x >> 4 ^ 0x3);
    int b = !((x & 0xa) ^ 0xa);
    int c = !((x & 0xc) ^ 0xc);
    return a & !(b | c);
}

要想完成这个目的,我们需要进行两个判断:低 4 4 4 位满足大于等于 0 0 0 并且小于等于 9 9 9 ,高四位等于 3 3 3

对于低四位,如果不满足这个条件,那么它对应的位为 0xa 或0xc ,可以通过异或进行判断,对于高四位,可以通过移位加上异或来判断。

conditional(x, y, z)

等同于 x ? y : z 这样的操作

int conditional(int x, int y, int z) {
    x = !!x;
    x = ~x + 1;
    return (x & y) | (~x & z);
}

这道题如果想到了把 x x x 变成全 0 0 0 或者全 1 1 1 的形式就会比较容易做,通过前两行代码,当 x = 0 x = 0 x=0 时, x x x 的二进制位就是全 0 0 0 的,否则是全 1 1 1 的形式。

isLessOrEqual(x, y)

x ≤ y x \le y xy 时返回 1 1 1, 否则返回 0 0 0

int isLessOrEqual(int x, int y) {
    int neg_x = ~x + 1;
    int sub_x = y + neg_x;
    int tmin = 1 << 31;
    int xsign = !!(x & tmin);
    int ysign = !!(y & tmin);
    int sub_x_sign = sub_x & tmin;
    return (!(xsign ^ ysign) & !sub_x_sign) | ((xsign ^ ysign) & xsign);
}

分符号位相同和符号位不同来分类讨论,符号位相同时,需要满足 y − x ≥ 0 y - x \ge 0 yx0 ;符号位不同时,需要满足 x < 0 x < 0 x<0

logicalNeg(x)

不用 !运算符来实现 !的功能

int logicalNeg(int x) {
    int c = ~x + 1;
    return ((x | c) >> 31) + 1;
}

x = 0 x=0 x=0 时, − x = x -x = x x=x ,我们可以利用这个性质来实现 !运算符的功能。

howManyBits(x)

用补码表示 x x x 的最小位数

int howManyBits(int x) {
    int bit0, bit1, bit2, bit4, bit8, bit16;
    int sgn = x >> 31;
    x = (~sgn & x) | (~x & sgn);
	//判断高16位是否存在1,如果存在,则说明最少有16位,下面同理
    bit16 = !!(x >> 16) << 4;
    x = x >> bit16;
    bit8 = !!(x >> 8) << 3;
    x = x >> bit8;
    bit4 = !!(x >> 4) << 2;
    x = x >> bit4;
    bit2 = !!(x >> 2) << 1;
    x = x >> bit2;
    bit1 = !!(x >> 1);
    x = x >> bit1;
    bit0 = x;
    return bit16 + bit8 + bit4 + bit2 + bit1 + bit0 + 1;
}

对于正数来说,我们需要找到最高位的 1 1 1 所在的位置,然后加上符号位。对于负数,我们需要找到最高位的 0 0 0 所在的位置,然后加上符号位。对于负数的情况,我们可以进行转换,把 0 0 0 变成 1 1 1,把 1 1 1 变成 0 0 0 ,这样就变成了正数的情况。

floatScale2(uf)

对于浮点参数 f,返回 2*f 的位级等价数

unsigned floatScale2(unsigned uf) {
    unsigned sign = uf & (1 << 31);
    unsigned e = (uf & 0x7f800000) >> 23;
    if(e == 0xff) return uf;
    if(e == 0) return sign | uf << 1;
    e++;
    if(e == 0xff) return sign | 0x7f800000;
    return (e << 23) | (uf & 0x807fffff);
}

首先对特殊的值进行判断,如果是 N a n Nan Nan 或者无穷大,直接返回 u f uf uf本身即可,对于无穷小的情况,返回乘 2 2 2 后的结果并且加上符号位。对于其他情况则将阶码的值加 1 1 1, 然后返回就可以了。
部分题目参考这篇文章

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 好的,这里是您要求的回答: 这个问题涉及到计算机系统的实验课程——深入理解计算机系统(CS:APP)的第一个lab任务,也称为Data Lab。这个任务要求学生使用C语言编写函数来实现不同的位级操作,从而深入理解计算机中数字的存储和运算。 ### 回答2: 在Data Lab的第二部分中,我们学习了如何用不超过十六个操作来实现不同的位运算。这些操作包括移位,逻辑运算,比较和掩码等。通过这些操作的实现,我们可以进一步理解底层计算机系统中位运算的实现原理。 在实现这些操作时,我们需要了解底层计算机系统的运算和数据类型。如符号扩展、零扩展和反码等。同时,在编写代码时需要熟练使用位运算的操作符号以及一些基本控制流语句如循环、条件语句等。 除了实现这些基本操作,我们也需要应用这些操作来解决一些实际问题。例如,实现一个函数,将一个十六进制数按位翻转,或是计算一个整数二进制表示中1的数量等。 通过Data Lab的学习,我们深入了解了计算机系统中底层的位运算实现原理,并学会了如何用简洁高效的代码实现这些操作。同时,这些操作也常常被用在各种领域的计算机编程中,对于未来的学习与工作都有很大的帮助。 ### 回答3: 在《深入理解计算机系统》lab1:data lab(二)中,我们主要学习了位运算和两个的补码表示。这些知识对于我们了解计算机的原理和编码方式非常重要。 在这个实验中,我们需要完成一些与位运算相关的任务。其中包括: 1. 实现位运算。我们需要用 C 语言实现一些常见的位运算,如与、或、非、异或、左移、右移等。 2. 计算 x 的相反数。 3. 检查 x 是否为零。 4. 判断 x 的符号是否为负数。 5. 计算 x 和 y 的和,但不能使用加法运算。 为了完成这些任务,我们需要对 C 语言数据类型的细节和位运算的机器级实现有一定的了解。例如,我们要了解有符号整数和无符号整数的区别,以及它们在机器上的表示方式。我们还需要理解位运算的计算过程,包括位移的规则、符号扩展和逻辑运算等。 通过这个实验,我们可以更深入地理解计算机的工作原理,学会用底层的方式实现高级的运算,掌握常用的位运算技巧。这对于提高编程的效率和代码的可读性都有很大帮助。同时,这也为后续的计算机科学学习打下了坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值