CSAPP实验lab1的补充

文章讨论了一系列与位操作相关的编程问题,包括如何实现异或操作、判断最小值、检测最大值、提取奇数位、检查ASCII数字、条件运算、比较大小、逻辑取反、计算所需位数以及浮点数到整数和反之的转换。这些问题涉及到整数和浮点数的位表示、溢出处理以及位运算在数值计算中的应用。
摘要由CSDN通过智能技术生成

Q1 bitxor

思路:分别计算x和y的补集(这里即为取反)与原值的按位与(&)运算的结果,然后将这两个结果进行按位与运算,再取反,得到最终的异或结果。具体来说,假设x和y的某一位分别为a和b,则异或的结果为a XOR b。如果a和b相等,则异或的结果为0;否则为1。

Q2 tmin

思路:首先,1左移31位,得到一个二进制数,其最高位为1,其余位为0,即为-2(w-1)。注意在补码表示中,最高位为符号位,表示整数的正负,因此-2(w-1)的二进制表示为1后面跟着w-1个0。因此,将1左移31位得到的值即为-2^(w-1)

Q3 isTmax

isTmax是一个函数,用于判断给定的整数是否为int类型的最大值,即0x7FFFFFFF。如果给定的整数是int类型的最大值,则返回1;否则返回0
实现:先将x加1得到y,然后将x和y加起来取反得到一个结果,该结果可以区分出x是否等于0x7FFFFFFF。具体来说,如果x是0x7FFFFFFF,则y等于0x80000000,x+y等于-1,其补码表示为全1;否则,y等于x+1,x+y等于0,其补码表示为全0。因此,我们可以将x+y的补码取反,得到-1或0,再将y取逻辑非,得到1或0,最后将两个结果进行按位与操作即可判断x是否等于0x7FFFFFFF

Q4 allOddBits

要求:allOddBits用于判断一个int类型的数的所有奇数位(从低位开始数,第1位、第3位、第5位等)是否都为1
实现思路:构造一个掩码,使得掩码的所有奇数位都为1,然后将给定的整数和掩码进行按位与操作,得到一个结果。如果该结果等于掩码,则说明给定的整数的所有奇数位都为1;否则,说明给定的整数的某个奇数位为0。最后将该结果取逻辑非,即可得到函数的返回值。掩码的构造方法是:将0xAA左移0、8、16、24位分别得到四个字节,然后将它们相加得到一个32位整数。这个32位整数的所有奇数位都为1,偶数位都为0。因此,将该整数作为掩码可以将给定的整数的所有奇数位提取出来。
注意:allOddBits函数使用了常数0xAA,这是因为0xAA的二进制表示中,所有奇数位都为1,偶数位都为0,即为我们所需要的掩码

Q5 isAsciiDigit

要求:先将x转换成数字,然后检查这个数字是否在0到9的范围内。
实现:它利用了算术右移操作和位与运算来实现这一目的
注意:其中有一步为x-48其原理是x减去了48(即ASCII码中数字’0’的编码值),即int adjust = ~(1 << 31) + 48。这是因为在ASCII编码中,数字’0’到’9’的编码分别为48到57。因此,将x减去48后,若结果在区间零到九内,则说明x代表一个数字字符

Q6 conditional

要求:通过将x转换为一个条件值,然后使用条件运算符(?:)来选择y或z中的一个值。
实现算法:利用了逻辑非运算、减1运算、位与运算和位或运算
思路:对x进行逻辑非运算(!x),得到一个值,如果x为零,则该值为1;否则,该值为0。对上一步得到的值进行减1得到一个值,如果x为零则该值为-1;否则,该值为0。将上一步得到的值保存在变量condition中,它的值为-1或0;将y和z按位与上condition和其取反后的值(~condition),得到两个值,然后将这两个值进行或运算,得到函数的返回值。

Q7 isLessOrEqual

思路:先获取x和y的符号位,然后计算x-y的符号位。接着分别使用逻辑运算符和位运算符实现了三个判断条件,最后使用按位或运算符将三个判断条件的结果合起来得到最终比较的结果
注意:需要保证x和y的取值范围,避免超出范围造成溢出

Q8 logicalNeg

思路:先对x取反加1得到它的相反数,然后使用位运算符和移位运算符计算了x和其相反数的符号位,并将其存储在变量s中,最后将变量加1并使用按位与运算符和掩码0x00000001确保它的返回值为0或1

Q9 howManyBits

要求:它是一个函数,接收一个整数x并返回一个整数,表示x在二进制补码表示下所需的位数
实现思路:获取x的符号位并将x的符号位扩展到所有位上,然后根据x的值在二进制补码表示下的规律,使用位运算符和移位运算符计算所需的位数,并将结果存储在变量中,最后将变量加1用来考虑符号位,并返回所需的位数

Q10 float_twice

思路:取出给定的浮点数的指数部分和尾数部分;判断给定的浮点数是否是NaN、无穷大或0:如果是NaN或无穷大,则直接返回该浮点数本身;如果是0,则返回0;否则执行下一步。判断给定的浮点数是否是规格化数:如果是规格化数,则将其指数部分加1再乘以2;如果是非规格化数,则将其尾数部分左移1位后再乘以2;将修改后的指数部分和尾数部分重新组合成一个32位无符号整数,并返回该整数
注意:这里的NaN代表一个“不是数字”的值,但是它的类型是number

Q11 float_i2f

题目:
/*

  • float_i2f - Return bit-level equivalent of expression (float) x
  • Result is returned as unsigned int, but
  • it is to be interpreted as the bit-level representation of a
  • single-precision floating point values.
  • Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
  • Max ops: 30
  • Rating: 4
    */
    代码实现
    unsigned float_i2f(int x) {
    unsigned sign, exp, frac, abs_x;
    int shift_left, shift_right;

if (x == 0) { // 如果x等于0,则直接返回0
return 0;
}

if (x < 0) { // 如果x是负数,则将其取绝对值并记录符号位
sign = 0x80000000;
abs_x = -x;
} else { // 如果x是非负数,则符号位为0
sign = 0x00000000;
abs_x = x;
}

// 计算exp和frac
shift_left = 0;
while ((abs_x & 0x80000000) == 0) { // 找到abs_x的最高位为1的位置
abs_x <<= 1;
shift_left++;
}
shift_right = 31 - shift_left; // 计算frac应该右移的位数
exp = (unsigned)(shift_right + 127) << 23; // 计算exp
frac = (abs_x & 0x7FFFFFFF) >> 8; // 计算frac

return sign | exp | frac;
}
思路:判断给定的整数是否为0:如果是0则直接返回0;否则执行下一步;判断给定的整数的符号:如果是负数则记录符号位,并将其取绝对值;但若是非负数,则符号位为0;找到给定整数的二进制表示中最高位为1的位置,从而计算frac应该右移的位数和exp;计算frac和exp;将符号位、exp和frac重新组合成一个32位无符号整数,并返回该整数。
注意:float_i2f函数中使用了常数127、0x80000000、0x7FFFFFFF和0x00800000,这是因为这些常数对应的二进制表示分别为指数部分为127、符号位为1、所有位都为1和指数部分为1、尾数部分都为0,用于计算exp和frac

Q12 float_f2i

/*

  • float_f2i - Return bit-level equivalent of expression (int) f
  • for floating point argument f.
  • Argument is passed as unsigned int, but
  • it is to be interpreted as the bit-level representation of a
  • single-precision floating point value.
  • Anything out of range (including NaN and infinity) should return
  • 0x80000000u.
  • Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
  • Max ops: 30
  • Rating: 4
    */
    代码实现:
    int float_f2i(unsigned uf) {
    int sign = (uf>>31)&1;
    int E = ((uf&0x7f800000)>>23) - 127;
    int frac = (uf&0x7fffff)|0x800000; //'|'用来不上默认的最高位
    if (E < 0)
    return 0; //E<0,x<1,最后舍入得到0
    if (E > 31)
    return 0x80000000; //out of range, return this
    if (E < 23)
    frac = (frac>>(23-E)); //小数位右移相应位数得到x的右部
    else if (E > 23)
    frac = (frac<<(E-23)); //小数位左移
    frac = frac&(1<<E);
    if (sign) //对负数进行转化
    return ~frac+1;
    else
    return frac;
    }
    要求:将给定的浮点数按照整数的格式进行解析,然后返回解析后的整数
    思路:将给定的无符号整数分别解析为符号位、指数部分和尾数部分;判断给定的浮点数是否为NaN或无穷大:如果是NaN或无穷大则返回0x80000000,否则执行下一步;计算将尾数部分转换为整数时需要右移的位数和左移的位数;如果是负数则将给定的浮点数转换为补码表示,将补码表示的浮点数右移从而得到最终的整数值

Q13 negate

这里顺序错了一点漏掉了
要求:实现一个函数,该函数能够将一个整数取反
注意:需要考虑到整数溢出的情况,在本实验中,如果输入整数是最小的负数,将会产生溢出,一旦溢出将无法对其进行取反操作
实现步骤:首先判断输入整数的正负性如果是正数则将其变为负数;如果是负数则将其变为正数。然后将输入整数转换成补码表示,以便进行二进制取反操作,接着对补码表示的整数进行二进制取反操作,将取反后的补码转换回原码表示最后返回取反后的整数

Q11 Q12

这两道题非常蒙蔽看了很久才有那么一丁点理解,还是太菜了,加油吧!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值