CSAPP Lab01——Data Lab完成思路

陪你把想念的酸拥抱成温暖

陪你把彷徨写出情节来

未来多漫长再漫长还有期待

陪伴你 一直到 故事给说完

——陪你度过漫长岁月

完整代码见:CSAPP/datalab-handout at main · SnowLegend-star/CSAPP (github.com)

01 bitXor

这道题是用~和&计算x^y

异或是两个二进制数a,b对应的位相同为0,不同为1。既然是aibi 不同才为,且只能用~和&两种位运算符号。考虑对a取反,再和b进行&操作。这样当ai =0,bi =1时可以得到1;但是还得考虑当ai =1,bi =0时也应该得到1,此时考虑的对b取反,再和a进行&操作。综合以上两点,我们可以初步得到式子为“(~a&b)|(a&~b)”,换算后得到“~(~(x & ~y) & ~(~x & y))”。

//1
/* 
 * 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 ~(~(x & ~y) & ~(~x & y));
}

 

02 tmin

返回最小二进制补整数

Tmin不就是0x8000 0000吗?注意这里可以用到的整数在0~0xAA之间,所以是“1<<31”。

/* 
 * tmin - return minimum two's complement integer 
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 4
 *   Rating: 1
 */
int tmin(void) {
  //正数的补码是它本身,负数的补码是取反加一
  return 1<<31;

}

03 isTmax

如果x是二进制补码的最大值,则返回1,否则返回0

       Tmax=0x7FFF FFFF,从Tmax的特殊性来考虑。如果x=Tmax,则x+1+x可以得到0xFFFF FFFF=Tmin。对于Tmin进行取反,则可以得到0。再对0取!,则可以令函数返回1。除此之外,还要考虑如果x本身就为Tmin,则它也会满足上述运算。所以得用^操作排除这种情况。

/*
 * isTmax - returns 1 if x is the maximum, two's complement number,
 *     and 0 otherwise 
 *   Legal ops: ! ~ & ^ | +
 *   Max ops: 10
 *   Rating: 1
 */
int isTmax(int x) {
  //二进制补码的最大值是:最高位0,其它位1
  int temp=x+1;
  int temp2=x+temp;
  //还得考虑x本身就是0xffffffff的情况,即x!=temp2
  return !(~temp2)&!!(x^temp2);

}

04 allOddBits

如果word中所有的奇数位为1,则返回1,否则返回0(位从0~31位)

       这题十分恶心,是第一个卡住我的。开始想得太简单了,以为满足条件的数字只有0xAAAA AAAA这一个。后来发现0xFFAA AAAA这种也可以,这就让我犯了难——对于0xFF这种形式要怎么判断呢?想了很久都没有头绪。跳过这题后面再写的时候灵光一闪,想到只要判断奇数位是1就行,根本就不用考虑偶数位。要做到这一步其实就是把x和0xAAAA AAAA进行&操作,可以提取出x奇数为上所有的1得到数字x2。我们会发现,只要x满足条件,那进行上一步操作后的形式都是统一的0xAAAA AAAA。所以最后判断x2是不是与0xAAAA AAAA一致就行。

/* 
 * 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
 */
int allOddBits(int x) {//没搞出来
  //计算机的右移位运算默认是逻辑还是算数呢?dev c++是逻辑
  //直接不用考虑偶数位的情况,只考虑奇数位全为1的时候
  //怎么在dev c上跑x=0x80000000的时候返回0,这时候就返回1了?????
  int a=0xAA<<8;
  int b=a+0xAA;     //b=0xAAAA
  int c=(b<<16)+b;  //这里b<<16得加括号,因为+的优先级大于<<
  int d=!((c&x)^c); 
  return d;//强行令偶数位全为0再进行比较
}

05 negate

返回-x

       简单的取反加一操作。最开始还在考虑Tmin的特殊性,验算后发现Tmin也符合这个规律。秒了,芜湖

/* 
 * negate - return -x 
 *   Example: negate(1) = -1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 5
 *   Rating: 2
 */
int negate(int x) {
  return ~x+1;
}

06 isAsciiDigit

如果0x30 <= x <= 0x39,返回1,否则返回0

       开始我的思路是挨个判断x的每一位。即x的第5、6位只能为1,再高位只能为0;对于低四位,第4位为1的时候只有第1位可以同时为1,如果第4位为0则后三位无论是什么值都可以。但是挨个判断每一位需要的符号好像会超过限制。

       后来看了别的解法,第一次发现了符号位的大用。基本上这次的lab都没提供“-”这个操作,但是可以利用“+(~x+1)”来实现减法。如果给出x,只要用两个边界值0x30和0x39对x进行减法操作就行。最后通过符号位来判断x与0x30和0x39的大小。这种思路在后面的题目也会用到。

/* 
 * 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
 */
int isAsciiDigit(int x) {
  //判断第四五位都是1、且高位都是0,1-3位值得小于等于9
  //x做完移位运算后自身值不发生改变的
  int a=x+~(0x30)+1;
  int b=0x39+~x+1;
  int c=a>>31;
  int d=b>>31;
  return !c&!d;
}

07 conditional

用位级运算表示三目运算符 x?y:z

       我们要注意到一点,这种返回值在几个数中选一个的势必得用到“|”操作,比如T01要是能用上“|”就会简单许多。由于只要x不为0就返回y,为0才返回z。要返回y,就是考虑当x不为0时让y和0xFFFF FFFF进行&操作。一个全新的操作在我脑中应运而生,那就是“!!x”。只要x不为0,那!!x就会得到1;x为0,那!!x会得到0。而对0或者1进行取反加一就可以得到0或者0xFFFF FFFF。这样我们就得到了想要的全1二进制数。此题结束。

/* 
 * conditional - same as x ? y : z 
 *   Example: conditional(2,4,5) = 4
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 16
 *   Rating: 3
 */
int conditional(int x, int y, int z) {
  
  return y&(~(!!x)+1)|(z&~(~(!!x)+1));
}

08 isLessOrEqual

如果x<=y,则返回1,否则返回0

       这题算是T06的弱化版。T06还得进行两次比大小,这题只用比一次就行了。也是用减法然后进行符号位的判断就可以解决。

/* 
 * 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) {
  int a=y+(~x+1);
  int b=x>>31&1;
  int c=y>>31&1;
  return (b&!c)|(!(a>>31)&!(b^c));//得控制后半部分只有同号的时候才能计算 
}

09 logicalNeg

用其余的操作符实现

       这题算是第二题卡了我很久的。想了一个多小时也没头绪——要如何才能做到当x不为0时返回0?假如从x的每一位着手,只要发现有一位不为0就可以判断x不为0,但是这样就要用到for循环了。遂跳过这题。

后来第二天再看的时候灵光一闪。既然对x的每位进行判断有困难,那还是老样子直接考虑数字这个整体。由于题目提供的运算符也不多,所以x的正负性成了可以拿来解题的性质。注意到一点,只要x不为0,那x的相反数符号位就和x的符号位是不同的。从正负性和符号位着手这题就很容易解决了。

/* 
 * 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 
 */
int logicalNeg(int x) {//不会 
  //果然过一天再搞就会有新思路,利用相反数符号的性质

  int x2=~x+1;
  int sign=(x>>31)^(x2>>31);
  int min=x>>31;
  return (~sign)&1&~((x2^x)^min);
}

10 howManyBits

使用补码时最少需要多少比特位

       这题的运算符限制是90,给人一种代码结构肯定十分庞大的感觉,倒是让我一下子不知如何下手。首先考虑的是把数字x和 ​​​​​​​​​​​​​​​​​​​​​ 进行比较,但这样用到的运算符数目必然会超过90。于是又想到了用二分法,但是二分法得结合for循环才好实施吧。最后又想到了一种二分法的变体。即x先和 ​​​​​​​ 比较,若是大于它就对x进行“>>16”的操作,然后再和 ​​​​​​​ 相比;小于它就直接和 ​​​​​​​ 进行比较。在不断的比较和移位操作中应该是可以判断出来的。

但是写其他题已经是花费了许多心力,遂开摆。等什么时候状态好了再来拿下这题。

/* 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
 */
int howManyBits(int x) { //开摆,不想写了
  int temp=x>>31;       //记录x的正负性
  int a=~x+1;
  int b=(1<<16)+a;
  int c=b>>31;          //用符号位判断2^16和x的大小

  return 0;
}

11 floatScale2

给定一个无符号数f,我们以浮点数的格式来看待这个数f,返回2*f

       首先得明白浮点数大致有三种类型:规格数,非规格数,无穷大或者NaN。然后提取出f的exp和frac部分。若f不是非规格数,对它进行判断再返回。若是规格数就好办了,直接在exp部分加上1就能返回了。

       值得一提的是,非规格数如果尾数最高位为1时,右移1位会使阶码最低位从0变为1,而这时候恰好就是正确的结果,并不需要额外的处理。这是因为乘2之后完成了进位,刚好规格数在小数点前有一个1,规格数和非规格数从而无缝衔接。

/* 
 * 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
 */
unsigned floatScale2(unsigned uf) {
  //先提取阶码位
  int exp=uf & 0x7f800000;
  int frac=uf & 0x7fffff;
  if(uf==0x7f800000||uf==0xff800000)
    return uf; 
  else if(exp==0x7f800000&&frac!=0)
    return uf;
  else if(exp==0)
    return (uf&0x80000000)+(frac<<1);//记得给位运算加括号
  else
    return uf + 0x800000;
}

12 floatFloat2Int

给定一个无符号数f,我们以浮点数的格式来看待这个数f,将这个浮点数f转换为整形。

       上来就考虑两个边界,即浮点数太小就返回0;太大就返回0x80000000u。我们知道,浮点数的计算方法是“”,其中E=e-127。故当e<127的时候,这个数整体就<1了。当e>127+30的时候,E>=31,直接达到了32bit能表达的数据上限。其他情况就是套用此式即可。

/* 
 * 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 floatFloat2Int(unsigned uf) {
  int exp=(uf & 0x7f800000)>>23;
  int frac=uf & 0x7fffff;
  if(exp>127+30)//无穷大或者是NaN都返回统一的值
    return 0x80000000u;
  else if(exp<127){//非规格化的数,
    return 0;
  }
  if(uf>>31)
  	return -(((frac>>23)+1)<<(exp-0x7F));
  else 
    return ((frac>>23)+1)<<(exp-0x7F); 
}

 

13 floatPower2

返回2的x次方,返回用无符号数表示的浮点数

当e<-126时,这已经是浮点数能表示的最小值了,所以返回0。当e>127,浮点数表示不出来这种数字,只能返回无穷大了。其他的情况E=x+bias,左移23位即可。

/* 
 * 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
 */
unsigned floatPower2(int x) {
  if(x<-126)
    return 0;
  else if(x>127)
    return (0xFF)<<23;
  return (x+127)<<23;
  return 2;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/694754.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Android Compose 十:常用组件列表 监听

1 去掉超出滑动区域时的拖拽的阴影 即 overScrollMode 代码如下 CompositionLocalProvider(LocalOverscrollConfiguration provides null) {LazyColumn() {items(list, key {list.indexOf(it)}){Row(Modifier.animateItemPlacement(tween(durationMillis 250))) {Text(text…

接口(API)开发,测试工具-apifox

前言 为什么需要接口&#xff08;API&#xff09;? 因为不同的平台或系统可能使用不同的技术栈、编程语言或数据格式。API提供了一个标准化的方式&#xff0c;使得这些不同的系统可以相互交换数据和功能调用&#xff0c;实现互操作性 在开发日常的项目交互中&#xff0c;不…

英伟达的GPU(4)

更第四篇&#xff0c;上周有点私事&#xff0c;恢复更新 上次的文章 英伟达的GPU(3) (qq.com) 书接前文&#xff0c;我们上章说要更新GPU的内存机制&#xff0c;本次就讲点这个 先做个定义&#xff0c;我们说内存&#xff08;显存&#xff09;&#xff0c;也分物理内存&#…

Linux系统推出VB6开发IDE了?Gambas,Linux脚本编写

第一个Linux程序&#xff0c;加法计算加弹窗对话框,Gambas,linux版的类似VB6的IDE开发环境 一开始想用VB6的Clng函数转成整数&#xff0c;没这函数。 输入3个字母才有智能提示&#xff0c;这点没做好 没有msgbox函数&#xff0c;要用messagebox.warning 如果可以添加函数别名就…

【算法篇】求最长公共前缀JavaScript版本

题目描述 给你一个大小为 n 的字符串数组 strs &#xff0c;其中包含n个字符串 , 编写一个函数来查找字符串数组中的最长公共前缀&#xff0c;返回这个公共前缀。 数据范围&#xff1a; 数据范围:0<n<5000&#xff0c;0<len(strsi)< 5000 进阶:空间复杂度 O(1)&a…

2024年第三届数据统计与分析竞赛(B题)数学建模完整思路+完整代码全解全析

你是否在寻找数学建模比赛的突破点&#xff1f;数学建模进阶思路&#xff01; 详细请查 作为经验丰富的数学建模团队&#xff0c;我们将为你带来2024年第三届数据统计与分析竞赛&#xff08;B题&#xff09;的全面解析。这个解决方案包不仅包括完整的代码实现&#xff0c;还有…

Unity | Shader基础知识(番外:了解内置Shader-Standard<一>)

目录 前言 一、什么是Standard 二、Standard参数详解 1.了解着色前 2. 着色拆分 3.参数RenderingMode 4.参数Albedo 5.参数Metallic 三、作者的话 前言 有粉丝给我说&#xff0c;感觉自己内部自带的Shader都还不知道怎么用&#xff0c;希望我讲一下内置Shader。 那…

Docker Desktop - WSL distro terminated abruptly

打开 PowerShell 或以管理员身份运行的命令提示符。运行以下命令以列出已安装的 WSL 分发&#xff1a; wsl --list 运行以下命令以注销 Docker 相关的分发 wsl --unregister <distro_name> 将<distro_name>替换为实际的 Docker 相关分发的名称。将<distro_…

[书生·浦语大模型实战营]——LMDeploy 量化部署 LLM 实践

1.基础作业 1.1配置 LMDeploy 运行环境 创建开发机 创建新的开发机&#xff0c;选择镜像Cuda12.2-conda&#xff1b;选择10% A100*1GPU&#xff1b;点击“立即创建”。注意请不要选择Cuda11.7-conda的镜像&#xff0c;新版本的lmdeploy会出现兼容性问题。其他和之前一样&…

智能组网节点是什么?

智能组网节点是一种用于解决复杂网络环境下远程连接问题的关键技术。它是一种通过智能化的方式&#xff0c;在任何网络环境下实现不同地区之间快速组建局域网的解决方案。其中&#xff0c;【天联】组网就是一款优秀的智能组网节点产品&#xff0c;是北京金万维科技有限公司自主…

苍穹外卖笔记-07-菜品管理-增加、删除、修改、查询分页还有菜品起售或停售状态

菜品管理 1 新增菜品1.1 需求分析与设计1.2 代码开发文件上传新增菜品实现 1.3 功能测试 2 菜品分页查询2.1 需求分析和设计2.2 代码开发设计DTO类设计VO类Controller层Service层Mapper层 2.3 功能测试 3 删除菜品3.1 需求分析和设计3.2 代码开发Controller层Service层Mapper层…

Unity Standard shader 修改(增加本地坐标裁剪)

本想随便找一个裁剪的shader&#xff0c;可无奈的是没找到一个shader符合要求&#xff0c;美术制作的场景都是用的都标准的着色器他们不在乎你的功能逻辑需求&#xff0c;他们只关心场景的表现&#xff0c;那又找不到和unity标准着色器表现一样的shader 1.通过贴图的透明通道做…

【set】集合总结

一、Set Set集合是Collection的子接口,代表一种集合,此种集合是元素不重复. 有两个常用实现类 HashSet 是元素不重复,无序,主要是指遍历顺序和插入顺序不一致 TreeSet 是元素不重复,排序 LinkedHashSet不常用 二、HashSet 1.1 介绍 HashSet是Set的实现类 底层是由哈希表实…

区块链(Blockchain)调查研究(一)

文章目录 1. 区块链是什么&#xff1f;2. 区块链分类和特点3. 区块链核心关键技术3.1 共识机制3.2 密码学技术3.4 分布式存储3.5 智能合约 4. 区块链未来发展趋势5. 区块链能做什么、不能做什么&#xff1f;5.1 第一部分5.2 第二部分5.3 第三部分&#xff08;结论&#xff09; …

④-1单细胞学习-cellchat单数据代码补充版

目录 1&#xff0c;数据输入及处理 ①载入包和数据 ②CellChat输入数据准备 ③构建CellChat对象 ④数据预处理 2&#xff0c;细胞通讯预测 ①计算细胞通讯概率 ②提取配受体对细胞通讯结果表 ③提取信号通路水平的细胞通讯表 ④细胞互作关系可视化 1&#xff09;细胞…

java线程相关知识点

Java多线程涉及以下几个关键点 1.线程生命周期&#xff1a;理解线程从创建到销毁的各个阶段&#xff0c;包括新建、运行、阻塞、等待、计时等待和终止。 2.线程同步&#xff1a;掌握如何使用synchronized关键字和Lock接口来同步代码&#xff0c;防止数据竞争和死锁。 3.线程间通…

csrf与xss差别 别在弄乱了 直接靶场实操pikachu的csrf题 token绕过可以吗???

我们现在来说说这2个之间的关系&#xff0c;因为昨天的我也没有弄清楚这2者的关系&#xff0c;总感觉迷迷糊糊的。 xss这个漏洞是大家并不怎么陌生&#xff0c;导致xss漏洞的产生是服务器没有对用户提交数据过滤不严格&#xff0c;导致浏览器把用户输入的当作js代码返回客户端…

HCIA--NAT地址转换(复习)

先交换后路由&#xff1a; 1&#xff1a;在交换机上创建vlan&#xff0c;进入接口划分vlan&#xff0c;接着在交换机连接路由器的接口上建立trunk干道 2&#xff1a;在路由器上&#xff0c;先配置物理接口IP&#xff0c;接着在路由器上创建两个子接口&#xff0c;将建立的vla…

Fences 5 激活码 - 电脑桌面整理软件

提起桌面整理&#xff0c;经典老牌工具 Fences 必有一席之地&#xff0c;Stardock 发布了最新的 Fences 5 版本。 可以将文件和图标归类放入各个栅栏分区&#xff0c;并支持文件夹展开至桌面、分区置顶、淡化隐藏图标等功能&#xff0c;能让你的桌面焕然一新&#xff0c;不再混…

请求 响应

在web的前后端分离开发过程中&#xff0c;前端发送请求给后端&#xff0c;后端接收请求&#xff0c;响应数据给前端 请求 前端发送数据进行请求 简单参数 原始方式 在原始的web程序中&#xff0c;获取请求参数&#xff0c;需要通过HttpServletRequest 对象手动获取。 代码…