isLessOrEqual_位级实现

本文介绍了一种使用位运算符来判断两个整数大小的方法,并提供了两种不同的实现方式,旨在通过位级操作解决符号整数比较问题。

原题

/*
 * isLessOrEqual - if x <= y then return 1, else return 0
 *  	Example: isLessOrEqual(4,5) = 1.
 * 	Legal ops: ! ~ & ^ | + << >>
 * 	Max ops: 24
 * 	Rating: 3
*/
int isLessOrEqual(int x, int y) {
   
   
	return 2;
}

解释

请实现如下功能
输入 x, y (int)
当 x <= y 时 输出 1
不然的话 输出 0
请仅仅使用 以下符号:

  • ! 非
  • ~ 按位取反
  • & 与
  • ^ 异或
  • | 或
  • +算术加
  • << 左移
  • 算术右移
    可使用的符号数最多为24个

限制

请不要使用循环, 函数, 判断,
所使用的符号数不算上()
可使用的整数最大为 0xFF (255)

实现1


                
实现的15个函数功能,一共分为三种类型。 表 1 运算 函数名称 功能描述 难度等 最大操作数 bitXor(x, y) 只用 & 和 ~ 实现 x^y 1 14 getByte(x, n) 从字x中取出第n个字节 2 6 logicalShift(x, n) 逻辑右移 3 20 bitCount(x) 计算x中1的数目 4 40 conditional(x,y,z) 类似于C语言中的 x ? y : z 4 12 表 2 二进制补码运算 函数名称 功能描述 难度等 最大操作数 tmin() 返回最小的补码 1 4 fitsBits(x,n) x的补码是否可以表示成n 2 15 dividePower2(x,n) 计算x/(2n) 2 15 negate(x) 不用负号得到 -x 2 5 howManyBits(x) 计算表达 x 所需的最少数 4 90 isLessOrEqual(x,y) x <= y? 3 24 intLog2(x) 计算⌊log2(x)⌋(向下取整) 4 90 表 3 浮点数运算 函数名称 功能描述 难度等 最大操作数 floatAbsVal(uf) 计算f的绝对值的表示 2 10 floatScale1d2(uf) 计算0.5*f的表示 4 30 floatFloat2Int(uf) 计算(int)f的表示 4 30 bits.c文件: 这个是源码文件,里面包含了上述待实现的函数,已经给出函数原型。实验内容是按照每个函数的要求编写实现其功能的代码。例如: /* * bitXor - x^y using only ~ and & * Example: bitXor(4, 5) = 1 * Legal ops: ~ & * Max ops: 14 * Rating: 1 */ int bitXor(int x, int y) { return 2; } 函数名 bitXor 参数 int , int 功能实现 x^y 要求 只能使用 ~ 和 运算符,将结果返回。 你需要做的就是按照功能描述和最大操作数的要求,实现bits.c中的每个函数。上面的例子就是使用两个运算符~和|来实现运算符的功能,并且你所使用的运算符个数不能超过 Max ops: 14 个,这就需要你先去推理如何用~和|实现,然后写出表达式。bits.c中所有要实现的函数只允许使用! \ ~ & ^ | + << >>这8个操作符。 请同学们务必认真阅读bits.c文件中的说明、注意事项和示例。 实验操作 第0步:用git获取实验初始文件: 在虚拟桌面左边窗口的上方点击“GitLab”。 “点击复制”按钮,复制git仓库地址。 关闭上述界面,在左边窗口的上方点击“更多”,选择“剪切板“。 在剪切板中ctrl+v贴入git仓库地址。 关闭上述界面,在命令行界面中输入下述命令,你要把http地址替换成你的仓库地址,按照提示输入GitLab的用户名和密码: git clone http://172.16.2.166/2020302111371/expProject2026-674.git csapp-datalab 进入该目录,你就可以开始工作啦! 第2步:实现bits.c中的函数,使用dlc编译器检查代码是否满足编码要求,命令如下: unix> ./dlc bits.c dlc -e参数可以检查你使用的运算符数量。如果没有问题,则不返回任何提示。 第3步:使用btest程序测试函数功能正确性。编译btest程序并进行测试,命令如下: unix> make btest unix> ./btest 注意,只要修改了bits.c文件,就需要重新编译btest程序,命令如下: unix> make clean unix> make btest btest程序将自动运行很多组测试用例来检查你实现的函数,下面是一些btest的使用技巧: unix> ./btest -h #输出btest命令的帮助信息 unix> ./btest -f foo #测试指定函数foo的正确性 unix> ./btest -f foo -1 27 -2 0xf #指定输入参数,测试函数foo的正确性 对实验操作有不懂的地方,可参考csapp-datalab目录中的README文件。 实验评价 本实验的实验评价包括两部分:自动评测和实验报告。 自动评测 本地测试通过后,务必一定进行在线评测,否则没有成绩!!! 将bits.c文件拷贝到桌面上: unix> cp ./bits.c ~/Desktop
最新发布
09-30
<think>嗯,用户的问题是关于如何在限定操作符的情况下实现bits.c文件中的7个浮点数和运算相关函数。首先,我需要仔细分析每个函数的需求以及对应的限制条件。根据引用[2],bits.c中的每个函数都有特定的限制,比如不能使用某些操作符,整型变量不能使用条件分支等。因此,我需要确保每个函数的实现都符合这些规则,并且通过dlc检测工具的检查。 首先,tmin函数需要返回32补码的最小值。这应该是0x80000000,可以通过左移操作实现,例如1 << 31。但要注意符号的问题,所以直接左移31即可得到正确的结果。 接下来是fitsBits,判断x是否能用n补码表示。根据引用[3],可以通过将x左移(32-n)再右移回来,检查是否与原值相等。这可以通过异或操作和逻辑非来实现。例如,x == (x << (32 - n)) >> (32 - n),这样就能判断是否可以用n表示。 dividePower2函数需要计算x/(2^n),向零取整。对于正数,直接右移n即可,但负数需要处理舍入问题。可以使用(x + (1 << n) - 1) >> n来调整,但需要根据x的符号选择是否加上偏置。这里可能需要使用掩码和符号的判断。 negate函数是取负数,这可以通过取反加一实现,即~x + 1,这个比较简单。 howManyBits需要确定表示x所需的最小数。这可能需要计算x的二进制补码形式中最高有效置,然后加1(符号)。可以通过不断右移并检查非零实现,但需要注意处理正负数的情况,可能需要将负数取反后统一处理。 isLessOrEqual函数需要判断x <= y。可以通过计算y - x的符号,同时处理溢出情况。需要考虑两种情况:x和y同号时,y - x的符号为非负;或者x负y正时直接返回true,其他情况返回false。这里需要避免使用条件语句,而是通过运算和逻辑操作组合。 intLog2需要计算x的以2为底的对数,向下取整。这需要找到最高有效置。可以用类似二分法的方法,逐步确定最高置,例如先检查高16是否有1,再依次检查更低的,累计数。 在实现这些函数时,必须严格遵守操作符的限制,例如不能使用循环、条件语句,只能使用有限的操作符和逻辑运算符。例如,在isLessOrEqual中,可以用运算来获取符号,并结合异或和与操作来判断大小关系。同时,需要注意处理边界情况,如tmin的溢出问题,或者intLog2中x为0的情况(但根据题目描述,可能假设x>0)。 另外,引用[3]中提到的异或方法来判断是否相等,这在fitsBits函数中可能用到,即通过!( (x ^ ((x << (32 -n)) >> (32 -n))) )来判断是否相等。同时,符号扩展的处理也需要考虑,确保移操作的正确性。 对于每个函数,可能需要多次测试和调试,确保在btest中能够通过所有测试用例,并且dlc不报错。例如,dividePower2中的偏置加法需要根据符号来调整,可以通过符号右移得到掩码,然后与( (1 << n) -1 )进行与操作,再添加到x上,最后右移n。 总的来说,需要逐个分析每个函数的需求,利用运算技巧和已有的引用中的方法,结合符号的处理、移操作、逻辑运算等,来实现功能同时满足操作符的限制条件。</think>根据引用[2]和引用[3],在限定操作符条件下实现这些函数需要严格遵循运算规则。以下是关键实现方案: ### 1. tmin(最小补码整数) ```c int tmin(void) { return 1 << 31; } ``` 原理:32补码最小值是$-(2^{31})$,对应二进制`0x80000000`。使用左移运算符直接构造结果[^3] ### 2. fitsBits(n补码可表示) ```c int fitsBits(int x, int n) { int shift = 32 + ~n + 1; // 等价于32-n return !(x ^ ((x << shift) >> shift)); } ``` 原理:通过符号扩展逆过程验证可表示性。引用[3]的异或判断法确保数据无损转换 ### 3. dividePower2(向零取整除法) ```c int dividePower2(int x, int n) { int sign = x >> 31; return (x + (sign & ((1 << n) + ~0))) >> n; } ``` 原理:通过符号判断添加偏置值$(2^n-1)$,实现负数时的向上取整修正[^3] ### 4. negate(取负数) ```c int negate(int x) { return ~x + 1; } ``` 原理:利用补码定义,按取反后加1即得相反数 ### 5. howManyBits(最小表示数) ```c int howManyBits(int x) { int sign = x >> 31; x = (sign & ~x) | (~sign & x); // 取绝对值 int cnt = 0; cnt += (!!(x >> 16)) << 4; cnt += (!!(x >> (cnt + 8))) << 3; cnt += (!!(x >> (cnt + 4))) << 2; cnt += (!!(x >> (cnt + 2))) << 1; cnt += (!!(x >> (cnt + 1))); return cnt + 1; } ``` 原理:通过二分法定最高有效,时间复杂度$O(\log n)$ ### 6. isLessOrEqual(小于等于判断) ```c int isLessOrEqual(int x, int y) { int diff_sign = ((y + ~x + 1) >> 31) & 1; int sign_x = x >> 31; int sign_y = y >> 31; return (diff_sign | (!(sign_x ^ sign_y) & !diff_sign)) & (!(sign_y & ~sign_x)); } ``` 原理:通过符号分析和差值符号判断,避免直接相减的溢出问题[^2] ### 7. intLog2(以2为底对数) ```c int intLog2(int x) { int cnt = 0; cnt += (!!(x >> 16)) << 4; cnt += (!!(x >> (cnt + 8))) << 3; cnt += (!!(x >> (cnt + 4))) << 2; cnt += (!!(x >> (cnt + 2))) << 1; cnt += !!(x >> (cnt + 1)); return cnt; } ``` 原理:通过移检测最高有效置,时间复杂度$O(\log n)$
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值