int类型规则:
1. 只允许使用0-0xff的整数
2. 只允许存在函数参数和局部变量(无全局变量)
3.可使用的一元运算符! ~
4.可使用的二元运算符& ^ | << >>
5.只允许使用整数, 不可以使用联合体数组等
6.不允许使用任何控制结构
7.不允许使用任何宏或者定义宏
8.不允许定义任何/调用函数
您可以假设您的机器:
1.使用2s补码(32位整数表示)。
2.算术执行右移。
3.如果移位量小于0或大于31,则在移位时具有不可预测的行为。
Rate1:
一、bitXor(只允许使用~和|)
int bitXor(int x, int y) {
return (~(x&y))&(~(~x&~y));
}
思路:
(君离散数学本当上手)
二、timin(返回最小值)
int tmin(void) {
return (1<<31);
}
思路: 一开始看到没有参数懵逼的说, 然后看了下攻略发现直接返回一个数就行了, 那么可以考虑直接位移就行了,0xff<<24什么的也是可以哒!
三、isTmax(是否为最大补码)
这题不会看, 所以知乎大佬的:
int isTmax(int x) {
int i = x+1;
x=x+i;
x=~x;
i=!i;
x=x+i;
return !x;
}
(照搬知乎李明岳大佬)
Rate2:
四:allOddBits(判断参数x是否奇数位全为1)
int allOddBits(int x){
int mask=(0xAA)+(0xAA)<<8;
mask=mask+(mask<<16);
return !((~x&mask)^mask);
}
思路: 一开始思路是通过16次<<再+01操作构造的, 然后想想太傻逼了, 就去知乎学了一下, 顺便晓得了自己构造的码叫掩码, 然后就很简单了, 先获取所有奇数位再异或一下, 然后非就行了(题目还看错了, 我还以为偶数位要求全0的=。=)
五:negate(不用-取反)
int negate(int x) {
return ~x+1;
}
思路: 阿贝群
Rate3:
六:isAsciiDigit(j检测是否为ASCII)
知乎大佬写的:
int isAsciiDigit(int x) {
int sign=1<<31;
int lowest=~0x30,highest=~(sign|0x39);
lowest=sign&(lowest+1+x)>>31;
highest=sign&(highest+x)>>31;
return !(lowest|highest);
}
自己的思路想打表的, 然后运算符超出限制了(
七:conditional(实现 : ? )
int conditional(int x, int y, int z) {
x=!!x;
x=~x+1;
return (y&x)|(z&~x);
}
思路: x为正得到x=00,x为非正得到x=0xff, &0代表清空多少位,&1代表保留多少位 |或一下,反正前后总有一个是0,|的话真的就和2选1一样
八:isLessOrEqual(实现 <= )
int isLessOrEqual(int x, int y) {
int a=y+(~x+1);
a=a>>31;
return !a;
}
思路:(~x+1)得到-x, y-x看正负, 再算数左移之后!一下即可
快全线崩溃的Rate4:
九:logicalNeg(计算!而不用!)
int logicalNeg(int x) {
return ((x|(~x+1))>>31)+1;
}
思路: 首先要记得-x为~x+1, 只有在x=0的情况下,x=-x, 则x| ~x会得到0, 其他情况都会在符号位因为正负的关系得到0和1, 则|之后会产生1, 之后我们再算术右移31再+1即可
十:howManyBits(计算有多少位)
知乎大佬的思路:
int howManyBits(int x) {
int b16,b8,b4,b2,b1,b0;
int sign=x>>31;
x = (sign&~x)|(~sign&x);//如果x为正则不变,否则按位取反(这样好找最高位为1的,原来是最高位为0的,这样也将符号位去掉了)
b16 = !!(x>>16)<<4;//高十六位是否有1
x = x>>b16;//如果有(至少需要16位),则将原数右移16位
b8 = !!(x>>8)<<3;//剩余位高8位是否有1
x = x>>b8;//如果有(至少需要16+8=24位),则右移8位
b4 = !!(x>>4)<<2;//同理
x = x>>b4;
b2 = !!(x>>2)<<1;
x = x>>b2;
b1 = !!(x>>1);
x = x>>b1;
b0 = x;
return b16+b8+b4+b2+b1+b0+1;//+1表示加上符号位
}
只能说过于精巧(照搬知乎李明岳大佬)
十一: floatScale2(2.0乘浮点数)
unsigned floatScale2(unsigned uf) {
int exp = (uf&0x7f800000)>>23;//exp为阶码,uf&0x7f800000只保留uf的阶码,并且逻辑右移23位移除尾数
int sign = uf&(1<<31);//sign为 阶符
if(exp==0) return uf<<1|sign;//如果阶码为0(非格式化),则2^(-2^7)*M,而非格式化中f=M所以只要做到尾数f整体左移1即可
if(exp==255) return uf;//如果exp ==0xff则为NaN,直接返回
exp++;//用于公式x=(-1)*M*2^E ,M=1+f,E=en...e0-Bias,则E++就可以做到2^(E+1)
if(exp==255) return 0x7f800000|sign;//返回无穷
return (exp<<23)|(uf&0x807fffff);//补上尾数
}
思路写在注释了, 部分情况没考虑到, 看了知乎大佬的
十二:floatFloat2Int(浮点数转换为整数)
int floatFloat2Int(unsigned uf) {
int s_ = uf>>31;
int exp_ = ((uf&0x7f800000)>>23)-127;
int frac_ = (uf&0x007fffff)|0x00800000;
if(!(uf&0x7fffffff)) return 0;
if(exp_ > 31) return 0x80000000;
if(exp_ < 0) return 0;
if(exp_ > 23) frac_ <<= (exp_-23);
else frac_ >>= (23-exp_);
if(!((frac_>>31)^s_)) return frac_;
else if(frac_>>31) return 0x80000000;
else return ~frac_+1;
}
没想出来, 看的李明岳大佬的
十三: floatPower2(2.0的指数运算)
unsigned floatPower2(int x) {
int Nan=0xff<<23;
int result=x+127;
if(result<=0)return 0;
if(result>=255)return Nan;
return result<<23;
}
思路:首先表示2.0, M*2^E, 则有M = 1+f, 所以2.0为(1)*2 ^1, 尾数全为0即可,而2.0的指数在阶码可直接体现, 所以用127+x即可得到2.0 ^x的表示, 剩下的就是考虑范围了, 如果127+x>=255则返回越界就好, 如果是小数则直接返回0就好, 这是题目所要求的
总结:
datalab总共做了三天, 其中有四道题完全不会, 还有一道题考虑的不够周到, r4难度很多想了大半天也想不出来= =, 所以后来做的有点崩溃, 希望以后复习的时候能多康康吧, 这个lab还是很能锻炼人对浮点数和整数的理解的, 虽然浮点数过了段时间还是要忘(悲