by Gu Wei
2021年9月
在bits.c文件中
x1//12/* 3 * bitXor - x^y using only ~ and & 4 * Example: bitXor(4, 5) = 15 * Legal ops: ~ &6 * Max ops: 147 * Rating: 18 */9/*实现异或运算,用离散知识易得*/10int bitXor(int x, int y) {11 return ~(~(~x&y)&~(x&~y));12}13/* 14 * tmin - return minimum two's complement integer 15 * Legal ops: ! ~ & ^ | + << >>16 * Max ops: 417 * Rating: 118 */19/*最小的二进制补码就是100...0*/20int tmin(void) {21 return 1 << 31;22}23//224/*25 * isTmax - returns 1 if x is the maximum, two's complement number,26 * and 0 otherwise 27 * Legal ops: ! ~ & ^ | +28 * Max ops: 1029 * Rating: 130 */31/**32 * 题意:判断x是否为最大的二进制补码数33 * 相反数等于自己的数有min以及0,这里利用该性质实现函数34 * 若x是max,x+1后成了min35 * 又利用-x == ~x+1 (这是显然的36 * 通过异或^运算判断是否相等:a^b == 0 iff a == b37 * 最后还要排除x==0的情况38*/39int isTmax(int x) {40 x += 1;41 return (!(x^(~x+1)))&(!!x);42}43/* 44 * allOddBits - return 1 if all odd-numbered bits in word set to 145 * where bits are numbered from 0 (least significant) to 31 (most significant)46 * Examples allOddBits(0xFFFFFFFD) = 0, allOddBits(0xAAAAAAAA) = 147 * Legal ops: ! ~ & ^ | + << >>48 * Max ops: 1249 * Rating: 250 */51/**52 * 题意:判读x的奇数位是否全为153 * 照着移移就知道了54 */55int allOddBits(int x) {56 x = x & (x >> 2);57 x = x & (x >> 4);58 x = x & (x >> 8);59 x = x & (x >> 16);60 return (x & 2) >> 1;61}62/* 63 * negate - return -x 64 * Example: negate(1) = -1.65 * Legal ops: ! ~ & ^ | + << >>66 * Max ops: 567 * Rating: 268 */69
70/**71 * 题意:实现相反数72 * 这为什么会是rating2?这不是简单的结论吗,甚至之前的isTmax也用到了该性质73 */74int negate(int x) {75 return ~x + 1;76}77//378/* 79 * isAsciiDigit - return 1 if 0x30 <= x <= 0x39 (ASCII codes for characters '0' to '9')80 * Example: isAsciiDigit(0x35) = 1.81 * isAsciiDigit(0x3a) = 0.82 * isAsciiDigit(0x05) = 0.83 * Legal ops: ! ~ & ^ | + << >>84 * Max ops: 1585 * Rating: 386 */87/**88 * 题意:return 1 if 0x30 <= x <= 0x39 89 * 注意:!x == 1 iff x == 0, e.g.!(-1) = 0;90 * 利用a + ~b+1 实现a-b91 * 利用最高位(31位)是否为1来判断x是否为负数:当a<0时,a>>31==-1;当a>=0时,a>>31==092 * 故当a<0时!(a>>31)==0;当a>=0时!(a>>31)==193 */94int isAsciiDigit(int x) {95 return !((~0x30 + x + 1)>>31) & !((~x + 0x39 + 1)>>31);96}97/* 98 * conditional - same as x ? y : z 99 * Example: conditional(2,4,5) = 4100 * Legal ops: ! ~ & ^ | + << >>101 * Max ops: 16102 * Rating: 3103 */104/**105 * 题意:x ? y : z 106 * 利用掩码选择y与z107 * 利用x设置掩码mask为0xFFFFFFFF或者0x0108 */109int conditional(int x, int y, int z) {110 int tmp = !x;111 int mask = ~tmp + 1;112 return (~mask & y) + (mask & z);113}114/* 115 * isLessOrEqual - if x <= y then return 1, else return 0 116 * Example: isLessOrEqual(4,5) = 1.117 * Legal ops: ! ~ & ^ | + << >>118 * Max ops: 24119 * Rating: 3120 */121/**122 * 题意:if x <= y then return 1, else return 0123 * 简单地利用!((y+~x+1)>>31)存在溢出问题,使判断式出错。需要由符号是否相同分类。124 * 利用difSign作为掩码,当正负性相同时,difSign为0,否则为-1125 * 这样综合利用conditional和isAsciiDigit中的方法即可解决126 */127int isLessOrEqual(int x, int y) {128 int difSign = (x^y)>>31;129 return (~difSign&!((y+~x+1)>>31))+(difSign&(!(y>>31)));130}131//4132/* 133 * logicalNeg - implement the ! operator, using all of 134 * the legal operators except !135 * Examples: logicalNeg(3) = 0, logicalNeg(0) = 1136 * Legal ops: ~ & ^ | + << >>137 * Max ops: 12138 * Rating: 4 139 */140/**141 * 题意:实现!142 * 利用 只有0和它的相反数同时满足最高位为0 的特点实现143 */ 144int logicalNeg(int x) {145 return ~((x|(~x+1))>>31)&1;146}147/* howManyBits - return the minimum number of bits required to represent x in148 * two's complement149 * Examples: howManyBits(12) = 5150 * howManyBits(298) = 10151 * howManyBits(-5) = 4152 * howManyBits(0) = 1153 * howManyBits(-1) = 1154 * howManyBits(0x80000000) = 32155 * Legal ops: ! ~ & ^ | + << >>156 * Max ops: 90157 * Rating: 4158 */159/**160 * 题意:求表示x的二进制补码的最小位数161 * 我这么理解的:二分查找最高位1的位置,最后加上符号位即可162 * 一开始把负数x取非,为了把最前面无效的1给去掉163 */164int howManyBits(int x) {165 int b16,b8,b4,b2,b1,b0;166 int sign=x>>31;167 x = (sign&~x)|(~sign&x);//如果x为正,则x不变;如果x为负,则x改为~x168 // 不断缩小范围169 b16 = !!(x>>16)<<4;//高十六位是否有1170 x = x>>b16;//如果有(至少需要16位),则将原数右移16位171 b8 = !!(x>>8)<<3;//剩余位高8位(i.e.8-15位)是否有1172 x = x>>b8;//如果有(至少需要16+8=24位),则右移8位173 b4 = !!(x>>4)<<2;//同理174 x = x>>b4;175 b2 = !!(x>>2)<<1;176 x = x>>b2;177 b1 = !!(x>>1);178 x = x>>b1;179 b0 = x;180 return b16+b8+b4+b2+b1+b0+1;//+1表示加上符号位181}182//float183/* 184 * floatScale2 - Return bit-level equivalent of expression 2*f for185 * floating point argument f.186 * Both the argument and result are passed as unsigned int's, but187 * they are to be interpreted as the bit-level representation of188 * single-precision floating point values.189 * When argument is NaN, return argument190 * Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while191 * Max ops: 30192 * Rating: 4193 */194/**195 * 注释:float数都是把unsigned int当作float来使的196 */197/**198 * 题意:如果uf为特殊值(i.e.exp全为1)返回uf,否则返回2*uf199 */ 200unsigned floatScale2(unsigned uf) {201 unsigned exp = uf>>23;202 unsigned ans;203 //NaN and inf,i.e.exp全为1,直接返回uf204 if(!((exp&0xFF)^0xFF))205 return uf;206 //non-normalized 直接左移207 /**208 * 这里有一个精妙的点,关于frac的最高位为1的情况209 * 此时把uf左移一位,frac最高位变成了exp的最低位,uf从非规格化数变成了规格化数210 * 由于规格化和非规格化E和M的精妙设置,uf左移一位就直接正确了,做到了很好的平稳过渡211 */ 212 if(!(exp&0xFF))213 {214 unsigned sign = uf>>31<<31;215 return (uf<<1)|sign;216 }217 //normalized 指数部分加一218 /**219 * 这里也有一个小细节,我们无法通过修改frac来使uf变成两倍,只能通过exp加一的方法220 * 于是,当exp加一后变成全是一后,就是inf情况,需要再把frac置零即可221 */222 ans = (1<<23)+uf;223 //inf224 if (!((exp&0xFF)^0xFF))225 return ans>>23<<23;226 else227 return ans;228}229/* 230 * floatFloat2Int - Return bit-level equivalent of expression (int) f231 * for floating point argument f.232 * Argument is passed as unsigned int, but233 * it is to be interpreted as the bit-level representation of a234 * single-precision floating point value.235 * Anything out of range (including NaN and infinity) should return236 * 0x80000000u.237 * Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while238 * Max ops: 30239 * Rating: 4240 */241/**242 * 题意:实现float到int的强制类型转换243 * 特别的,Anything out of range (including NaN and infinity) should return 0x80000000u.244 */ 245int floatFloat2Int(unsigned uf) {246 int E = ((uf>>23)&0xFF)-127;247 int sign = uf>>31;248 unsigned M = (uf&0x7FFFFF)|0x800000; //加上1,非规格化数已经在E<0的时候被排除了。严格的说这里的M是M * 2^23249 250 if(E<0) return 0; //由于M<2,所以E<0时必为纯小数251 if(E>=31) return 0x80000000u; //超出范围。提示:int范围为-2^31~2^31-1,0x80000000u=-2^31,NaN和inf也涵盖252 253 //M是一个23位小数,又注意到这里的M其实是M * 2^23254 if(E>23) M <<= E-23;255 else M >>= 23-E;256
257 if(sign) return ~M+1;//负数258 else return M;//正数259}260/* 261 * floatPower2 - Return bit-level equivalent of the expression 2.0^x262 * (2.0 raised to the power x) for any 32-bit integer x.263 *264 * The unsigned value that is returned should have the identical bit265 * representation as the single-precision floating-point number 2.0^x.266 * If the result is too small to be represented as a denorm, return267 * 0. If too large, return +INF.268 * 269 * Legal ops: Any integer/unsigned operations incl. ||, &&. Also if, while 270 * Max ops: 30 271 * Rating: 4272 */273/**274 * 题意:返回2^x的浮点型275 * 其实不难,就分类讨论276 */ 277unsigned floatPower2(int x) {278 //float最大为(2-2^-23)·2^127,小于2^128279 if (x>127)280 return 0xFF<<23; //返回+inf281 else if (x<-149) return 0;//float最接近0的数为2^-149,[00..001]282 else if (x>=-126) //规格化数283 {284 int exp = x + 127;285 return exp << 23;286 }287 else //-126>x>=-149,非规格化288 {289 int t = 149 + x;290 return (1 << t);291 }292}测试如下:
xxxxxxxxxx181linux> ./dlc bits.c2# 无输出则说明代码符合要求3linux> ./btest4Score Rating Errors Function5 1 1 0 bitXor6 1 1 0 tmin7 1 1 0 isTmax8 2 2 0 allOddBits9 2 2 0 negate10 3 3 0 isAsciiDigit11 3 3 0 conditional12 3 3 0 isLessOrEqual13 4 4 0 logicalNeg14 4 4 0 howManyBits15 4 4 0 floatScale216 4 4 0 floatFloat2Int17 4 4 0 floatPower218Total points: 36/36满分即可