前天讲到要刚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实验笔记的更多相关文章

  1. 【CSAPP】Shell Lab 实验笔记

    shlab这节是要求写个支持任务(job)功能的简易shell,主要考察了linux信号机制的相关内容.难度上如果熟读了<CSAPP>的"异常控制流"一章,应该是可以不 ...

  2. 【CSAPP】Cache Lab 实验笔记

    cachelab这节先让你实现个高速缓存模拟器,再在此基础上对矩阵转置函数进行优化,降低高速缓存不命中次数.我的感受如上一节,实在是不想研究这些犄角旮旯的优化策略了. 前期准备 我实验的时候用到了va ...

  3. 【CSAPP】Architecture Lab 实验笔记

    archlab属于第四章的内容.这章讲了处理器体系结构,就CPU是怎样构成的.看到时候跃跃欲试,以为最后实验是真要去造个CPU,配套资料也是一如既往的豪华,合计四十多页的参考手册,一大包的源码和测试程 ...

  4. 【CSAPP】Attack Lab实验笔记

    attacklab这节玩的是利用一个字符串进行缓冲区溢出漏洞攻击,就小时候想象中黑客干的事儿. 做题的时候好几次感叹这些人的脑洞,"这都可以攻击?还能这么注入?这还可能借力打力?" ...

  5. 【CSAPP】Bomb Lab实验笔记

    bomblab这节搞的是二进制拆弹,可以通俗理解为利用反汇编知识找出程序的六个解锁密码. 早就听闻BOMBLAB的大名,再加上我一直觉得反汇编是个很艰难的工作,开工前我做好了打BOSS心理准备.实际上 ...

  6. 【CSAPP】Performance Lab 实验笔记

    perflab这节的任务是利用书中知识,来对图像处理中的Rotate和Smooth操作函数进行优化.这次没对上电波,觉得学了一堆屠龙之技.于我个人理解,现在计算机配置比以前高多了,连SWAP分区都几近 ...

  7. ChCore Lab3 用户进程和异常处理 实验笔记

    本文为上海交大 ipads 研究所陈海波老师等人所著的<现代操作系统:原理与实现>的课程实验(LAB)的学习笔记的第三篇:用户进程与异常处理.所有章节的笔记可在此处查看:chcore | ...

  8. CS:APP配套实验 Data Lab

    刚刚完成注册博客,想写一篇随笔,方便以后自己回顾.如果恰好也能帮助到你,是我的荣幸. 这次随笔是记载我的计算机系统(CS:APP,Computer Systems:A Programer's Pers ...

  9. SQL*Loader实验笔记【二】

      所有SQL*Loader实验笔记 实验案例总结(1-7):     SQL*Loader实验笔记[一] 实验案例总结(8-13):   SQL*Loader实验笔记[二] 实验案例总结(14-19 ...

随机推荐

  1. cornerstone 忽略不必要文件

    转:https://www.jianshu.com/p/f48207baa0cd

  2. Redis 集群方案什么情况下会导致整个集群不可用?

    有 A,B,C 三个节点的集群,在没有复制模型的情况下,如果节点 B 失败了, 那么整个集群就会以为缺少 5501-11000 这个范围的槽而不可用.

  3. @Qualifier 注解 ?

    当有多个相同类型的 bean 却只有一个需要自动装配时,将@Qualifier 注解和 @Autowire 注解结合使用以消除这种混淆,指定需要装配的确切的 bean.

  4. 以太网在汽车行业中的挑战——灵活的接口及软件使ECU开发不再复杂

    以太网在汽车行业中的挑战--灵活的接口及软件使ECU开发不再复杂 以太网将会在一批新车型中作为一个车载系统网络使用.因此,下一步就是以太网和现有汽车网络技术的集成,包括:CAN.FlexRay.LIN ...

  5. node+express+mysql 实现登陆注册

    基于 node.express.mysql 实现的登录注册. 1.`首先在终端中 安装 node .` 2.`通过npm install express -g 命令全局安装 express`. 3.` ...

  6. 前端react+redux+koa写的博客推荐

    React-Node搭建的博客 曾经用的php+mysql+js写的博客,现在看来已经很low了,所以用目前最火的react+koa框架重构一下.先上地址吧:目前线上版本http://www.liuw ...

  7. 界面跳转+信息传递+AS中如何将ADV转移到其他盘中

    今日所学:界面跳转 信息传递 遇到的问题: 昨天遇到不能新建java类,在网上百度了很多,大多原因是没有新建java类的模板,但是我有,换了一个新的新建的方式后,发现虽然能建立了,但在测试时还是不能页 ...

  8. swig模板引擎和ejs模板引擎

    swig模板引擎的基本用法: 1. 变量 {{ name }}  //name名前后必须要加空格,不加就会报错 2. 属性 {{ student.name }} 3. 模板继承 swig使用exten ...

  9. 关于javaweb学习终点的一些感悟

    学习完javaweb后,自己做了一套管理项目,使用了mybatis,themeleaf和servlet.大致明白了servlet的真实应用场景. 说白了servlet就是用来指定浏览器url后面输入了 ...

  10. python数据类型与基础运算

    注释:了解其他数据类型补充 基础数据类型补充 可以回一下之前的数据类型: 整型,浮点型,字串符和列表. 一.字典(dict) #字典:可以精准的储存数据 是用大括号表示'{}' '字典和数据数据列表差 ...