CSAPP DataLab
断断续续做了两天可算做的差不多,,
注意不同版本的题目可能会有所不同,搜了很多他们的题目和现在官网给的实验题都不一样,自己独立思考完整做一遍顺便记录一下。
PS:刚开始这些难度为1的题有的说实话我都做了挺久的,不过到后面虽然难度上升了,但是确越做越有感觉了,另外完整做一遍感觉很有意思,这些题总体感觉就是让你自己把那些运算符< ,> ? 什么的自己使用位级运算手动实现一遍,知道底层是怎样运作的。
一,
bitXor:
- /*
- * 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 ;
- }
题目如图,
题目解释:使用~ & 完成 ^ 位运算,虽然难度很低,但是我也推导了半天,,
思路:异或可以理解为取出a,b之中不相同的位,& 就是取出为都为1的位,那么我们可以先取出同为1的,然后取反,就得到了同为0或者不相同的位,即 ~(a&b) ,接着,我们取出同为0的,取反,得到同为1或者不相同的位,即~(~a&~b), 接着,再取这两个的交集,就是我们所需要的不相同的位。即
- int bitXor
- r(int x, int y) {
- return (~(x&y))&(~(~x & ~y));
- }
二
tmin:返回补码整数的最小值,补码表示就是有个符号位,int类型shi是4个字节,32位,所以最小值就是1<<31 ,符号位为1,其他位都为0
- /*
- * tmin - return minimum two's complement integer
- * Legal ops: ! ~ & ^ | + << >>
- * Max ops: 4
- * Rating: 1
- */
- int tmin(void) {
- return <<;
- }
三
isTmax:如果是补码最大值就返回1,否则返回0,Tmax是 0x7FFFFFFF,
虽然还是一个简单题,但是我又想了很久,而且感觉这样子很麻烦。。
思路:核心是利用溢出。
理性分析了一下,想要返回0,1,那么肯定要用到 ! 运算符,一个常数的非是0,除了!0=1,所以,我们需要构造出来一个表达式,让x为Tmax时候值刚好为0,其他情况值都为1,这样子取非,就可以得到结果了。我这里想的是如果X是Tmax,那么~x就是Tmin,所以判断~x是不是Tmin,利用溢出来判断,给~x加上-1(~0),Tmin情况下会产生溢出,然后会进行符号截断,Tmin-1 = Tmax,再利用Tmax+Tmin+1 = 0得到我们想要的0,再取非即可。
- int isTmax(int x) {
- return !((~x+~) + ~x + );
- }
四,
allOddBits:
五,
negate:输入一个x,返回-x,
思路:第一眼看过去感觉很简单,实际上就是很简单,直接取反加一就行了,取反刚好就是自己的相反数-1,再加上一就可以了,不知道这个题为什么难度是2
- /*
- * negate - return -x
- * Example: negate(1) = -1.
- * Legal ops: ! ~ & ^ | + << >>
- * Max ops: 5
- * Rating: 2
- */
- int negate(int x) {
- return (~x) + ;
- }
六,
isAsciiDigit:判断一个数是不是在 48-57,包括57,48.刚开始没什么思路,不过感觉肯定是要构建出来一个0或者1的在特定情况下,最后参考了一下网上的,说实话让我自己做肯定做不出来,感觉很巧妙
思路:这个题实际上就是为了判断两个表达式的真假,x-48>=0 和 x-57 <= 0 ,将这两个表达式转换一下, 用到了第五题的结论,-48=~48+1,-57=~57+1,判断>=0或者<=0,看符号位就可以了,符号位为1表示<0,符号位为0表示>=0,得到符号位自然是将这个32位数右移31位,
综上,我们得到下面结论,如果 (x+~48+1)>>31 为0,那么x>=48,如果 (x+~57+1)>>31 为1 ,那么x<57,然后取前者的非,和后者进行&运算,同时满足条件即说明x>=48,x<57。
很明显,漏掉了边界57,x=57时,x-57刚好为0,移位之后得到的是0,所以我们将第表达式二改为 (x+~58+1) x为57时,结果仍为负数,符号位为1,将57这种情况成功纳入到符号位为1的情况,
- *
- * isAsciiDigit - return if 0x30 <= x <= 0x39 (ASCII codes for characters '' to '')
- * Example: isAsciiDigit(0x35) = .
- * isAsciiDigit(0x3a) = .
- * isAsciiDigit(0x05) = .
- * Legal ops: ! ~ & ^ | + << >>
- * Max ops:
- * Rating:
- */
- int isAsciiDigit(int x) {
- return !((x + (~ + )) >> )&((x + (~ + )) >> );
- }
七
conditional:即自己使用位级符号实现一个三目运算符
这个题说实话没有看懂。。
八,
isLessOrEqual(x,y) 如果y>=x 返回1,否则返回0
这个题感觉思想和前面的很像,判断y-x>=0是否成立,即判断y-x的符号位,如果是0的话就表明成立,1表示不成立,因为符号位1表示为负数。这样子就简单了,-x = ~x+1 ,符号位>>31即可得到,所以可以构造出表达式:(y+~x+1)>>31 ,要求是成立了返回1,所以再取个非就可以了。
- /*
- * isLessOrEqual - if x <= y then return 1, else return 0
- * Example: isLessOrEqual(4,5) = 1.
- * Legal ops: ! ~ & ^ | + << >>
- * Max ops: 24
- * Rating: 3
- */
- //即使用位级运算判断y-x>=0表达式是否成立,看符号位
- int isLessOrEqual(int x, int y) {
- return !((y+(~x+))>>);
- }
九,
logicalNeg:使用其他的位级运算符实现 ! 运算,
。。刚开始思路错了,想着直接 x^0^1,忘记考虑了x是32位的,和0异或出来一般不会是1
思路:两种情况,一种是! 0 = 1, 其他数 ! num = 0,所以其实只要想办法把这两种情况区分开来就可以了。个人感觉区分的话肯定是要找出0的特点的,很明显,0的相反数是它本身,其他数的相反数是他的负数。利用这一点,我们可以让x的相反数(~x+1)的符号位(>>31)和x进行异或,除了0以外结果都是1,由于不能取反,所以用if判断一下就可以了。
- int logicalNeg(int x) {
- if((((~x+)>>)^(x>>)))
- return ;
- return ;
- }
十,
howManyBits:返回表达x最少需要多少位
思路:感觉跟十进制转换为2进制差不多。我想的是我们确定位数那么就需要判断x的范围,如果在 2^(i-1)---2^i 之间,那么就需要i位刚好可以表示,不过由于是有符号整数,所以需要再加上一位符号位,就是i+1位,所以我们只需要将logx的值向上取整,再加上1即可,这是对整数而言,对于负数来说,将负数转换为正数进行计算,最后同样加上一即可,至于确定x的范围,循环除2(>>1),直到x为0为止。不过这里有两种特殊情况,那就是Tmin和-1,Tmin由于是一个负数,如果取他的相反数进行计算的话,不存在与之对应Tmax,会导致不可预期的结果,另外-1只需要一位即可表示,+1需要两位,这两种特殊情况我想的是直接if判断一下,返回相应的值,如果有更好的方法欢迎讨论。
- int howManyBits(int x) {
- int i=; //符号位
- int y=x;
- if(x==-) //特殊情况
- return ;
- if(x==0x80000000)
- return ;
- if(x>>) //负数取相反数
- y = ~x+;
- while(y){
- y = y>>; // 除2
- i++;
- }
- return i;
- }
。。。剩下的浮点数的题,,,,浮点数那块看了几次都没看完,,等看完了再做吧!
CSAPP DataLab的更多相关文章
- CSAPP 之 DataLab 详解
前言 本篇博客将会剖析 CSAPP - DataLab 各个习题的解题过程,加深对 int.unsigned.float 这几种数据类型的计算机表示方式的理解. DataLab 中包含下表所示的 12 ...
- CSAPP:datalab实验记录
CSAPP:datalab实验记录 bitXor /* * bitXor - x^y using only ~ and & * Example: bitXor(4, 5) = 1 * Lega ...
- CSAPP:Lab1 -DataLab 超详解
写在前面 之前考研的时候csapp的书有刷过5,6遍,所以对书本知识还算比较了解.恰逢最近在学c++的时候,顺带刷一下大名鼎鼎的csapp实验. 0. 环境准备 最好准备一个纯净的Linux系统这里建 ...
- CSAPP实验——DataLab
任务:按照要求补充13个函数,会限制你能使用的操作及数量 bitXor(x,y) 只使用 ~ 和 & 实现 ^ tmin() 返回最小补码 isTmax(x) 判断是否是补码最大值 allOd ...
- 【CSAPP】Data Lab实验笔记
前天讲到要刚CSAPP,这一刚就是两天半.CSAPP果然够爽,自带完整的说明文档,评判程序,辅助程序.样例直接百万组走起,管饱! datalab讲的是整数和浮点数怎么用二进制表示的,考验的是用基本只用 ...
- 【DIY】【CSAPP-LAB】深入理解计算机系统--datalab笔记
title: 前言 <深入理解计算机系统>一书是入门计算机系统的极好选择,从其第三版的豆瓣评分9.8分可见一斑.该书的起源是卡耐基梅龙大学 计算机系统入门课(Introduction to ...
- 在Ubuntu下使用 csapp.h 和 csapp.c
它山之石可以攻玉. 对于<深入理解计算机系统>这本神人写就的神书, 我等凡人就不评论什么啦. 这本书的 第二,三 部分, 真的真的对我理解操作系统有很大的帮助. (当然, 如果你不看第一部 ...
- CSAPP读书随笔之一:为什么汇编器会将call指令中的引用的初始值设置为-4
CSAPP,即<深入理解计算机系统:程序员视角>第三版,是一本好书,但读起来确需要具备相当的基本功.而且,有的表述(中译文)还不太直白. 比如,第463页提到,(对于32位系统)为什么汇编 ...
- 深入理解计算机中的 csapp.h和csapp.c
csapp.h其实就是一堆头文件的打包,在http://csapp.cs.cmu.edu/public/code.html 这里可以下载.这是<深入理解计算机系统>配套网站. 在头文件的# ...
随机推荐
- Docker 核心技术
docker是什么?为什么会出现? 容器虚拟化技术:轻量级的虚拟机(但不是虚拟机) 开发:提交代码 ——> 运维:部署 在这中间,因为环境和配置,出现问题 ——> 把代码/配置/系统/数据 ...
- python3从入门到精通之数据类型,布尔类型介绍
数据的类型 为了更充分的利用内存空间以及更有效率的管理内存,变量是有不同的类型的. Number(数字) int(整型) float(浮点型) complex(复数) bool(布尔) String( ...
- linux装OpenOffice后传---中文乱码的解决
上一篇的博客已经详细的介绍了linux系统上如何安装OpenOffice,安装之后使用发现转换的pdf出现中文乱码.后来发现是linux上没有中文对应的那个字体. 字体准备 在windows上的位置 ...
- bat 下 字符串拆分 类似 split 可以使用 for /f delims
@echo offset strin=AA,BB,CC,DDfor /f "tokens=1,2,3,4 delims=, " %%a in ('echo %strin%') do ...
- .net core + mvc 手撸一个代码生成器
最近闲来无事,总想倒腾点什么,索性弄下代码生成器,这里感谢叶老板FreeSql的强大支持. 以前也用过两款不错的代码生成器,这里说说我的看法 1.动软代码生成器,优点很明显,免费,简单,但是没法高度自 ...
- 从SpringBoot构建十万博文聊聊高并发文章浏览量设计
前言 在经历了,缓存.限流.布隆穿透等等一系列加强功能,十万博客基本算是成型,网站上线以后也加入了百度统计来见证十万+ 的整个过程. 但是百度统计并不能对每篇博文进行详细的浏览量统计,如果做一些热点博 ...
- JMM浅析
背景 学习Java并发编程,JMM是绕不过的槛.在Java规范里面指出了JMM是一个比较开拓性的尝试,是一种试图定义一个一致的.跨平台的内存模型.JMM的最初目的,就是为了能够支多线程程序设计的,每个 ...
- ubuntu16.04双系统创建分区
ubuntu安装分区 安装ubuntu 图1:Ubuntu Linux分区向导 如果希望对分区过程进行完全控制,可以使用"其它"选项.单击"继续"按钮,安装向导 ...
- 【码上开心】Windows环境mysql数据库使用(一) 安装Mysql数据库
[下载MySql] https://dev.mysql.com/downloads/mysql/ 如下图,选择版本,本教程仅演示ZIP压缩包下载配置. 2.[解压到指定目录] 3.[配置环境变量] 4 ...
- ubuntu18.04安装docker
本文基于unbuntu18.04版本来安装docker,步骤如下: 1:右击桌面->打开终端(E). 2::输入以下命令: sudo snap install docker ,输入密码之后出下图 ...