【CSAPP】Data Lab实验笔记
前天讲到要刚CSAPP,这一刚就是两天半.CSAPP果然够爽,自带完整的说明文档,评判程序,辅助程序.样例直接百万组走起,管饱!
datalab讲的是整数和浮点数怎么用二进制表示的,考验的是用基本只用位运算来实现一些看似稀松平常的操作.实际体会就是看题五秒钟,脱发两小时.当然做出来的成就感也是爆棚的.
求异或
根据离散数学等值演算写出公式
//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);
}
求补码可表示的最小数
有且仅有最高位为1的数就是了
/*
* tmin - return minimum two's complement integer
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 4
* Rating: 1
*/
int tmin(void) {
return (1<<31);
}
求补码可表示的最大数
这题开始需要一个技巧:!!x可以把非零数变成1,把0变成0
tmax=0x7FFFFFFF
tmax+1=0x10000000
(tmax+1)+(tmax+1)=0x00000000
C语言形式写作: x=tmin()-1
变形得 x+1=tmin()
a ^ b仅在每一位都相同时为假,则可取反用!(a ^ b)表示仅在每一位都相同时为1
最后额外排除0xFFFFFFFF
//2
/*
* 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) {
return !((x+1)+(x+1))&!!(x+1);
}
判断所有偶数位是否均为1
令y=1010...1010(二进制),即y==0xAAAAAAAA
运用<<和+来让0XAA重复四次得到该值
当且仅当x的任意偶数位都为1时返回1
即x存在偶数位为0时返回0
即结果为!(~x&0XAAAAAAAA)
/*
* 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) {
int y=0xAA;
y=(y<<8)+y;
y=(y<<16)+y;
return !(~x&y);
}
求-x
根据公式直接写
/*
* negate - return -x
* Example: negate(1) = -1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 5
* Rating: 2
*/
int negate(int x) {
return (~x+1);
}
判断是否为'0'~'9'
!(a^b)在当且仅当a与b任意一位都相同时为1,可以代替==
查表得规律:
00...011100X表示38~39
00...0110XXX表示30~37
故借助于<<分别判断之
//3
/*
* 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) {
return !((x>>1)^0x1C) | !((x>>3)^0x6);
}
实现x?y:z
假设存在操作@,
x=1时有x@y=y
x=0时有x@y=0
联想到&的性质可知
x=111...111(二进制)时x&y=y
x=000...000(二进制)时x&y=0
而111...111(二进制)=0XFFFFFFFF=-1
再根据前面求负数的题,~a+1=-a
/*
* 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 ((~!!x+1)&y)|(~!x+1&z);
}
判断小于等于
直接求y-x在异号的时候会溢出
(x>>31)^(y>>31)判断xy符号位是否不同
sub=y-x=y+~x+1求差值
若同号,y-x<0时返回1
若异号,x<0时返回1
/*
* 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 sx=x>>31;
int sy=y>>31;
int diff=sx^sy;
int sub=(y+~x+1)>>31;
return ((!diff&!sub)|(diff&sx))&1;
/*
另一种方法:分x>=0?,y>=0?四种情况讨论
int xb=x>>31;
int xa=~xb;
int yb=y>>31;
int ya=~yb;
return (xa&((ya&!((y+~x+1)>>31))))|(xb&((ya&1)|(yb&!!((~y+x)>>31))));
*/
}
另一种思路:分x>=0?,y>=0?四种情况讨论
int isLessOrEqual(int x, int y) {
int xb=x>>31;
int xa=~xb;
int yb=y>>31;
int ya=~yb;
return (xa&((ya&!((y+~x+1)>>31))))|(xb&((ya&1)|(yb&!!((~y+x)>>31))));
}
实现!运算符
关键知识点:当且仅当x==0时,x与-x符号位相同,并且值为0
故判断~(-x|x)的符号位即可
//4
/*
* 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) {
return (~((~x+1)|x)>>31)&1;
}
另一种思路:我管这叫二分折叠
int logicalNeg(int x) {
int a=(x>>16)|x;
int b=(a>>8)|a;
int c=(b>>4)|b;
int d=(c>>2)|c;
int e=(d>>1)|d;
return (~e)&1;
}
判断位数
看Max ops知难度.
预处理:
把负数转换成它的~,使得正负数可用同一套操作
每个数都有一个符号位,所以计数器初始值为1
之后二分法:
判断高十六位是否为0,是的话把计数器加16,然后截取高十六位作为新的x;
否则节取低十六位作为新的x
判断高八位是否为0,是的话把计数器加8,然后截取高八位作为新的x;
否则节取低八位作为新的x
......
这个不断判断的过程可以借用前面x?y:z的代码,最后做一点点化简,防止超90ops
/* 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 ret=0;
int h16,h8,h4,h2,h1;
int sign=(x>>31)&1;
x=((~!!sign+1)&(~x))|(~!sign+1&x);
ret=1;
h16=(x>>16);
ret+=((~!!h16+1)&16);
x=h16|(~!h16+1&((x<<16)>>16));
h8=x>>8;
ret+=((~!!h8+1)&8);
x=h8|(~!h8+1&((x<<8)>>8));
h4=x>>4;
ret+=((~!!h4+1)&4);
x=h4|(~!h4+1&((x<<4)>>4));
h2=x>>2;
ret+=((~!!h2+1)&2);
x=h2|(~!h2+1&((x<<2)>>2));
h1=x>>1;
ret+=((~!!h1+1)&1);
ret+=!!x;
return ret;
进一步化简后:
int howManyBits(int x) {
int b16,b8,b4,b2,b1;
int ret=0;
int sign=(x>>31);
x=(~sign&x)|(sign&~x);
ret=1+!!x;
b16=!!(x>>16)<<4;
x=x>>b16;
b8=!!(x>>8)<<3;
x=x>>b8;
b4=!!(x>>4)<<2;
x=x>>b4;
b2=!!(x>>2)<<1;
x=x>>b2;
b1=!!(x>>1);
return b16+b8+b4+b2+b1+ret;
}
求浮点数f*2
if-else解封了还有啥难得?分类讨论,一个坑点在于无符号数右移的时候是无符号右移
//float
/*
* 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) {
unsigned e=(uf<<1)>>24;
if(e==0xFF) return uf;
else if(e==0) return (uf<<1)+(uf&0x80000000);
else return uf+(1<<23);
}
float转int
注意了<<和>>都不能超过自身的范围,也不能用负数,否则可能发生不可预期的错误
/*
* 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) {
unsigned f=((uf<<11)>>11)+(1<<23);
unsigned e=(uf<<1)>>24;
int sign=(uf>>31)&1?-1:1;
int shift=e-127-23;
if(e==0xFF) return 0x80000000;
else if(e==0) return 0;
else{
if(shift<-23) return 0;
else if(shift>10) return 0x80000000;
else if(shift<0) return (f>>(-shift))*sign;
else return (f<<shift)*sign;
}
}
求2.0^x
这题我竟然超时了.原因是我是在移动硬盘上装得linux,而评判程序恰好时运行在本地的,这样子速度就慢了一截,结果就超时了.
/*
* 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<=-127) return 0;
if(x>=128) return 0x7f800000;
return (127+x)<<23;
}
【CSAPP】Data Lab实验笔记的更多相关文章
- 【CSAPP】Shell Lab 实验笔记
shlab这节是要求写个支持任务(job)功能的简易shell,主要考察了linux信号机制的相关内容.难度上如果熟读了<CSAPP>的"异常控制流"一章,应该是可以不 ...
- 【CSAPP】Cache Lab 实验笔记
cachelab这节先让你实现个高速缓存模拟器,再在此基础上对矩阵转置函数进行优化,降低高速缓存不命中次数.我的感受如上一节,实在是不想研究这些犄角旮旯的优化策略了. 前期准备 我实验的时候用到了va ...
- 【CSAPP】Architecture Lab 实验笔记
archlab属于第四章的内容.这章讲了处理器体系结构,就CPU是怎样构成的.看到时候跃跃欲试,以为最后实验是真要去造个CPU,配套资料也是一如既往的豪华,合计四十多页的参考手册,一大包的源码和测试程 ...
- 【CSAPP】Attack Lab实验笔记
attacklab这节玩的是利用一个字符串进行缓冲区溢出漏洞攻击,就小时候想象中黑客干的事儿. 做题的时候好几次感叹这些人的脑洞,"这都可以攻击?还能这么注入?这还可能借力打力?" ...
- 【CSAPP】Bomb Lab实验笔记
bomblab这节搞的是二进制拆弹,可以通俗理解为利用反汇编知识找出程序的六个解锁密码. 早就听闻BOMBLAB的大名,再加上我一直觉得反汇编是个很艰难的工作,开工前我做好了打BOSS心理准备.实际上 ...
- 【CSAPP】Performance Lab 实验笔记
perflab这节的任务是利用书中知识,来对图像处理中的Rotate和Smooth操作函数进行优化.这次没对上电波,觉得学了一堆屠龙之技.于我个人理解,现在计算机配置比以前高多了,连SWAP分区都几近 ...
- ChCore Lab3 用户进程和异常处理 实验笔记
本文为上海交大 ipads 研究所陈海波老师等人所著的<现代操作系统:原理与实现>的课程实验(LAB)的学习笔记的第三篇:用户进程与异常处理.所有章节的笔记可在此处查看:chcore | ...
- CS:APP配套实验 Data Lab
刚刚完成注册博客,想写一篇随笔,方便以后自己回顾.如果恰好也能帮助到你,是我的荣幸. 这次随笔是记载我的计算机系统(CS:APP,Computer Systems:A Programer's Pers ...
- SQL*Loader实验笔记【二】
所有SQL*Loader实验笔记 实验案例总结(1-7): SQL*Loader实验笔记[一] 实验案例总结(8-13): SQL*Loader实验笔记[二] 实验案例总结(14-19 ...
随机推荐
- SpringAOP 失效解决方案、Spring事务失效
SpringAOP 失效解决方案 SpringAOP是基于代理来对目标方法进行增强,但是有的时候又会出现"增强无效"的情况,比如在@Transactional下的某类中的方法内调用 ...
- JSP和Servlet有哪些相同点和不同点?
JSP是Servlet技术的扩展,本质上是Servlet的简易方式,更强调应用的外表表达.JSP编译后是"类servlet". Servlet和JSP最主要的不同点在于,Servl ...
- ubuntu18.04设置开机自启Django
设置开机自启: rc-local.server [Unit] Description=/etc/rc.local Compatibility ConditionPathExists=/etc/rc.l ...
- Java 中怎么获取一份线程 dump 文件?
在 Linux 下,你可以通过命令 kill -3 PID (Java 进程的进程 ID)来获取 Java 应用的 dump 文件.在 Windows 下,你可以按下 Ctrl + Break 来获取 ...
- Redis 相比 Memcached 有哪些优势?
1.Memcached 所有的值均是简单的字符串,redis 作为其替代者,支持更为丰 富的数据类 2.Redis 的速度比 Memcached 快很 3.Redis 可以持久化其数据
- 学习git(一)
一.自动化运维 1.网络层(接入层.汇聚层.核心层): 1 LB+HA(L4.L7): 2 服务层(reverse proxy cache.应用层.web层.SOA层.分布式层.DAL): 3 数据层 ...
- CEPH-3:cephfs功能详解
ceph集群cephfs使用详解 一个完整的ceph集群,可以提供块存储.文件系统和对象存储. 本节主要介绍文件系统cephfs功能如何灵活的使用,集群背景: [cephadmin@yq01-aip- ...
- css技术之用最高和最宽的限制“max-height和max-width”做图片同比例缩放,达到图片不变形目的,做出批量打印图片功能,页面打印“window.print()”
一.简介 他们是为流而生的,像width/height这种定死的砖头式布局,min-width/max-width就没有存在的意义 ,min-width/max-width一定是自适应布局或流体布局中 ...
- 4.4 ROS节点名称重名
4.4 ROS节点名称重名 场景:ROS 中创建的节点是有名称的,C++初始化节点时通过API:ros::init(argc,argv,"xxxx");来定义节点名称,在Pytho ...
- 《深入理解ES6》笔记——块级作用域绑定(1)
本章涉及3个知识点,var.let.const,现在让我们了解3个关键字的特性和使用方法. var JavaScript中,我们通常说的作用域是函数作用域,使用var声明的变量,无论是在代码的哪个地方 ...