当前位置:网站首页>CSAPP Data Lab
CSAPP Data Lab
2022-08-11 02:22:00 【joker D888】
CS:APP Data Lab
前言
data lab主要考察位运算,补码,浮点数等相关内容,此lab能检验对整型,浮点数存储方式的理解,以及位运算的各种妙用,能够对整数浮点数的实际使用的过程中,对可能出现的“怪异”结果知其所以然。
以下13个函数即是本lab需要完成的内容,根据函数上方的注释及可用操作符限制补充完函数即可,部分函数不允许任何超过8bit的常量,详细内容查看相关注释。
lab资源下载点这里。
对于一些可能用到或了解的知识在最下方列出。
lab
bitXor
/* * bitXor - x^y using only ~ and & * Example: bitXor(4, 5) = 1 * Legal ops: ~ & * Max ops: 14 * Rating: 1 */ // 求x^y // 思路,先按位与求出x和y同为1的位,然后x,y分别和~c按位与,求出各自不同时为1的位a,b // 最后分别对a,b取反,使得各自位上同时为0或同时为1的位设为1,再将两者按位与后再取反,即得出不同时为1的位 int bitXor(int x, int y) { // x:4 y:5 int c = x & y; // 0100 int a = x & ~c; // 0000 int b = y & ~c; // 0001 int ret = ~a & ~b; // 1110 return ~ret; // 0001 // 或,不是同时为0和不是同时为1的两种情况进行按位与 // return ~(~x & ~y) & ~(x & y); }tmin
/* * tmin - return minimum two's complement integer * Legal ops: ! ~ & ^ | + << >> * Max ops: 4 * Rating: 1 */ // 求Tmin // 将1左移31位,这样除了最高符号位其余全为0,即可取得最小值 int tmin(void) { return 1 << 31; }isTmax
/* * isTmax - returns 1 if x is the maximum, two's complement number, * and 0 otherwise * Legal ops: ! ~ & ^ | + * Max ops: 10 * Rating: 1 */ // 判断x是否是Tmax // 若x是Tmax,那么x+1=Tmin,而~Tmin=Tmax,所以可以以此验证,此外当x=-1时,由于溢出也满足这个等式,还需要特判一下 // 利用异或和逻辑非来判断等式是否成立,!!(x+1)来判断x是否为-1,!!是将数字转化为true或false int isTmax(int x) { return !(~(x + 1) ^ x) & !!(x + 1); }allOddBits
/* * allOddBits - return 1 if all odd-numbered bits in word set to 1 * where bits are numbered from 0 (least significant) to 31 (most significant) * Examples allOddBits(0xFFFFFFFD) = 0, allOddBits(0xAAAAAAAA) = 1 * Legal ops: ! ~ & ^ | + << >> * Max ops: 12 * Rating: 2 */ // 求x的二进制奇数位上全为1 // 如果奇数位上全为1,返回true int allOddBits(int x) { int a, b; a = 0xAA + (0xAA << 8); // 注意运算符优先级 a= a + (a << 16); // a的奇数位全为1,偶数位为0 b = a & x; // 如果x的奇数位上也全位1,等式的结果为a return !(a ^ b); // 用异或和逻辑非判断两者是否相等 }negate
/* * negate - return -x * Example: negate(1) = -1. * Legal ops: ! ~ & ^ | + << >> * Max ops: 5 * Rating: 2 */ // 求x的相反数 // 补码的非=补码取反+1 , -x=~x+1 int negate(int x) { return ~x + 1; }isAsciiDigit
/* * isAsciiDigit - return 1 if 0x30 <= x <= 0x39 (ASCII codes for characters '0' to '9') * Example: isAsciiDigit(0x35) = 1. * isAsciiDigit(0x3a) = 0. * isAsciiDigit(0x05) = 0. * Legal ops: ! ~ & ^ | + << >> * Max ops: 15 * Rating: 3 */ // 求x是否在0x30~0x39之间 // 即 00110000~00111001之间,发现4~5位固定是1,之后全0, // 而0~3位则从0000递增变化到1001,所以我们先判断高位的24个bit是否为0x3(a) // 再判断第3位是否为1(b),若为1,则判断1,2位上是否有1(c),利用b和c的按位与即可判断 int isAsciiDigit(int x) { int a = !(x >> 4 ^ 3); // 高位的24个bit是否为0x3 int b = !!(x & 8); // 第3位是否为1 int c = !!(x & 6); // 则判断1,2位上是否有1 return a & !(b & c); // 若高24bit为0x3,且低4位不超过0x9,return 1 }conditional
/* * conditional - same as x ? y : z * Example: conditional(2,4,5) = 4 * Legal ops: ! ~ & ^ | + << >> * Max ops: 16 * Rating: 3 */ // 模拟三元运算符 // 使用!x-1,即可将x的真假翻转,-1用~0来实现 int conditional(int x, int y, int z) { int a = !x + ~0; // 若x是0,a=0,否则a是全1 return (a & y) | (~a & z); }isLessOrEqual
/* * isLessOrEqual - if x <= y then return 1, else return 0 * Example: isLessOrEqual(4,5) = 1. * Legal ops: ! ~ & ^ | + << >> * Max ops: 24 * Rating: 3 */ // 模拟<= // if x<=y ,返回1,否则返回0 // 通过y-x的正负即可判断,但作差可能导致溢出,需要特殊考虑一下 int isLessOrEqual(int x, int y) { int sign_x = x >> 31 & 1; // x的符号位 int sign_y = y >> 31 & 1; // y的符号位 int a = y + (~x + 1); // y - x int sign_a = a >> 31 & 1; // a的符号位 // 若a最高位是0,即y-x>=0,应该返回1,但若x>0,y<0,那此时是负溢出造成的结果,应当返回0 // 若a最高位是1,即y-x<0,应该返回0,但若x<0,y>0,那此时是正溢出造成的结果,应当返回1 // 总上,返回1有两种可能,x,y符号相同且a最高位是0,以及x<0,y>0(符号位无所谓,x负y正,返回1即可) int nosame_xy = sign_x ^ sign_y; // 若x,y符号位不同为则为1 return (!sign_a & !nosame_xy) | (nosame_xy & sign_x); }logicalNeg
/* * logicalNeg - implement the ! operator, using all of * the legal operators except ! * Examples: logicalNeg(3) = 0, logicalNeg(0) = 1 * Legal ops: ~ & ^ | + << >> * Max ops: 12 * Rating: 4 */ // 实现逻辑非,0返回1,非0返回0 // 只有0的相反数是其本身,所以x^(-x) 只有当x为0时,结果为0,否则,结果是负数,最高位为1, // 同时需要注意,在补码中,-Tmin=Tmin,需要特判 // 所以将最高位提取出来与1异或即可 // 如果最高位是1,返回0,如果最高位是0,且x^(-x)的最高位是1,返回0 int logicalNeg(int x) { int sign_x = (x >> 31 & 1) ^ 1; // 如果符号位是1,等式结果为0,否则为1 int sign_xor = ((~x + 1) ^ x) >> 31 & 1; //提出 x^(-x)的最高位 return sign_x & (sign_xor ^ 1); // ^1 是为了翻转最低位 // 或,上面的用了10个ops,显然冗余了一些,简化如下 // 对于(~x+1)>>31,若x是正数,结果为-1,若x是负数数或0,结果是0,也就不用x^(-x)来判断了,但也需要特判 // 用 x|(~x+1>>31) 来表示,若结果为-1,则x不为0,若结果为0,则x为0。最后加上1返回即可 // return ((x | (~x + 1)) >> 31) + 1; }howManyBits
/* howManyBits - return the minimum number of bits required to represent x in * two's complement * Examples: howManyBits(12) = 5 * howManyBits(298) = 10 * howManyBits(-5) = 4 * howManyBits(0) = 1 * howManyBits(-1) = 1 * howManyBits(0x80000000) = 32 * Legal ops: ! ~ & ^ | + << >> * Max ops: 90 * Rating: 4 */ // 求x用二进制补码表示最少需要几位 // 若x为正数,显然求出其最左边的1的处于第几位,再加1表示符号位即可 // 若x为负数,则求出其最左边的0的位置,再加1表示符号位即可 // 为啥负数是找最左边的0呢,因为最高位符号位的权值,如11011(-5)而,1011(-5) // 可以发现,假设有w+1位,若符号位的紧邻右边的位也是1的话,先不管其余位,那么值为-(2^w)+(2^(w-1))=-(2^(w-1)) // 也就是说,与其1100...00,不如100...00这样表示,能使得位数更小,符号位紧邻右边有连续的1同理 // 我们不妨对x去反,这样就可以和正数一样找最左边的1 // 那么怎么找最左边的1呢,二分思想,一开始我们先看原x的高16位是否有1,若有则将x>>16,相当于砍掉x的低16位 // 若没有,则说明高16位全位0,不动,相当于砍掉x的高16位,以此8,4,2进行下去 int howManyBits(int x) { int b16,b8,b4,b2,b1,b0; int sign= x >> 31; // 若x是正数不变,若x是负数,按位取反,| 左边是为了应对负数,|右边是为了应对正数,各自的另一半则为0 x = (sign & ~x) | (~sign & x); // 二分思想 b16 = !!(x >> 16) << 4; //若高16位有1,二进制位的4位置为1,权值2^4=16 x = x >> b16; // 若有,此表示式将x右移16位,否则不变 b8 = !!(x >> 8) << 3; // 同理,高8位是否有1 x = x >> b8; b4 = !!(x >> 4) << 2; // 高4位是否有1 x = x >> b4; b2 = !!(x >> 2) << 1; // 高2位是否有1 x = x >> b2; b1 = !!(x >> 1); // 最1位是否有1 x = x >> b1; // 上面所谓的高几位是原x不断砍半后的二进制位,b0为了检验移位到最后剩下的两个bit位的最低位是否为1 b0 = x; return b16 + b8 + b4 + b2 + b1 + b0 + 1; //记得加上符号位 }floatScale2
/* * floatScale2 - Return bit-level equivalent of expression 2*f for * floating point argument f. * Both the argument and result are passed as unsigned int's, but * they are to be interpreted as the bit-level representation of * single-precision floating point values. * When argument is NaN, return argument * Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while * Max ops: 30 * Rating: 4 */ // 计算2*f,f是浮点数,不过参数和返回值都是无符号整形表示 // 首先,对于NaN,不用计算,直接返回,NaN的阶码部分全位1,尾数部分不为0, // 先求阶码exp=(uf0x7f800000)>>23 ,再求尾数 frac=uf&0x7fffff // 如果exp=255,并且尾数非0,那就是NaN,return uf即可,如果frac全0,表示无穷大,*2还是无穷大,也return uf即可 // 如果exp=0,非规格化形式,若frac=0,表示值为0,若frac!=0,表最接近0的那些数,可以统一处理为尾数*2,即frac<<=1,不用担心 // 如果exp!=0 && exp!=255,规格化形式,只需要把exp+1,即可 // 曾想过,为什么非规格化且不为0的时候为什么不能是exp+1,毕竟uf*2,不就是阶码+1,但非规格化和规格化一样处理的话 // exp+1后,就从非规格化变为了规格化,但float最小的非规格化为1.4*e-45,最小的规格化为1.2*e-38, // 显然比较小的非规格化按这种方式处理后,一跃变为了规格化,变大了不止两倍。 unsigned floatScale2(unsigned uf) { unsigned exp = (uf & 0x7f800000) >> 23; unsigned frac = uf & 0x7fffff; unsigned sign = uf >> 31 & 1; unsigned res; if(exp == 0xff) { return uf; }else if(exp == 0){ frac <<= 1; res = sign << 31 | frac; // 本应还要与上exp<<23,但此时exp全0就每必要了 }else{ ++exp; res = sign << 31 | exp << 23 | frac; } return res; }floatFloat2Int
/* * floatFloat2Int - 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型 // 如果原浮点数值为0,return 0, // 若指数大于31,溢出,返回0x80000000 // 若指数小于0,返回0 // 否则,把小数部分看为整数(即相当于小数部分整体左移了23位),再根据exp的大小,对小数部分进行最终调整 // 若exp>23,还得左移exp-23,若exp<23,说明左移多了,还得右移23-exp位 // 最后根据符号位进行正负调整,返回即可 // int floatFloat2Int(unsigned uf) { int sign = uf >> 31 & 1; // 取出符号位 int exp = ((uf & 0x7f800000) >> 23) - 127; // 指数 int frac = (uf & 0x007fffff) | 0x00800000; // 小数,且加上了1 // 若uf为0或指数小于0,返回0 if(!(uf & 0x7fffffff) || exp<0) return 0; // 若指数大于31,溢出 if(exp >= 31) return 0x80000000; else if(exp > 23) // 右移少了 frac <<= exp - 23; else // 右移多了 frac >>= 23-exp; if(sign) frac = -frac; return frac; }floatPower2
/* * floatPower2 - Return bit-level equivalent of the expression 2.0^x * (2.0 raised to the power x) for any 32-bit integer x. * * The unsigned value that is returned should have the identical bit * representation as the single-precision floating-point number 2.0^x. * If the result is too small to be represented as a denorm, return * 0. If too large, return +INF. * * Legal ops: Any integer/unsigned operations incl. ||, &&. Also if, while * Max ops: 30 * Rating: 4 */ // 计算2.0^x // 浮点数标准用V=(-1)^s * M * 2^E // 根据浮点数表示,x就是exp部分 // 根据int的范围进行讨论即可 // 单精度exp占8位,阶码E=e-Bias(2^7-1) ,即范围是[-126,127] // 若 x>=128,超过所能表示的最大值了,+INF // 若 >=-127, 在指数表示范围内,直接放入exp部分 // 若 x>=-150,exp部分能放127,frac有23位,根据标点数frac的含义,也可以用来表示,所以只要不小于150,都可以表示出来 // 若 x<150, 超出最小的表示范围了,return 0 unsigned floatPower2(int x) { if(x >= 128) return 0x7f800000; if(x >= -126) return (x + 127) << 23; if(x >= -150) return 1 << (x+150); return 0; }上方所有函数经测试结果如下

note





边栏推荐
猜你喜欢

OptiFDTD应用:用于光纤入波导耦合的硅纳米锥仿真

117. 本地开发好的 SAP UI5 应用部署到 ABAP 服务器时,中文字符变成乱码的原因分析和解决方案
![[Detailed explanation of C data storage] (1) - in-depth analysis of the storage of shaping data in memory](/img/a1/b1c04d44ea74560a0be55a3b715d25.png)
[Detailed explanation of C data storage] (1) - in-depth analysis of the storage of shaping data in memory

ARM development (4) How to read the chip manual for novice Xiaobai, bare metal driver development steps and pure assembly to achieve lighting, assembly combined with c lighting, c to achieve lighting

本周四晚19:00知识赋能第六期第5课丨OpenHarmony WiFi子系统

阿里亿级并发册 + 机器学习算法 + 面试册 + 优化册 + 代码册 笔记!!!

Alibaba 最新神作!耗时 182 天肝出来 1015 页分布式全栈手册太香了

TRCX: doping process analysis

Deep Learning【第二章】

最新国产电源厂家及具体型号pin-to-pin替代手册发布
随机推荐
Ninjutsu_v3_08_2020-安全渗透系统安装
本周四晚19:00知识赋能第六期第5课丨OpenHarmony WiFi子系统
shell脚本入门
数据存储全方案----详解持久化技术
2022年广东省安全员A证第三批(主要负责人)操作证考试题模拟考试平台操作
This Thursday evening at 19:00, Lesson 5 of the sixth phase of knowledge empowerment丨OpenHarmony WiFi subsystem
The latest domestic power supply manufacturers and pin-to-pin replacement manuals for specific models are released
MySQL - 一条SQL在MySQL中是如何被执行的?
软件测试面试题:谈谈你对 cmm 和 is9000 的认识?
SIT221 Data Structures and Algorithms课程辅导
gRPC基础概念:闭包
nvidia-smi:控制你的 GPU
【websocket】
Geogebra 教程之 04 Geogebra 小程序
项目构建工具-Gradle入门
88Q2110 access C45 phy address through C22
BUU刷题记录
Js prototype and prototype chain and prototype inheritance
【PHP】入门知识
PIFuHD配置记录