这是一个关于机器级的整数、浮点数表示和位运算的实验。要求用给定的操作符、尽可能少的操作数去实现对应的函数功能。
完整的实验包:链接: https://pan.baidu.com/s/1xUBi3XDlidPQFNexbjXoLw 密码: 2333
以下是全部函数的代码:
1 /*****************************计算log2(x)向下取整*******************************/ 2 int ilog2(int x) { 3 int bit_16, bit_8, bit_4, bit_2, bit_1; 4 bit_16 = (!!(x >> 16)) << 4; //如果x >> 16非零,则至少有16位 5 x = x >> bit_16; 6 bit_8 = (!!(x >> 8)) << 3; 7 x = x >> bit_8; 8 bit_4 = (!!(x >> 4)) << 2; 9 x = x >> bit_4; 10 bit_2 = (!!(x >> 2)) << 1; 11 x = x >> bit_2; 12 bit_1 = x >> 1; //还剩两位时,直接判断首位。bit_1 == 1,剩两位;bit_1 == 0,剩一位 13 return bit_16 + bit_8 + bit_4 + bit_2 + bit_1;
//实际是(bit_1 + 1)-1;由于向下舍入,总位数减一 14 } 15 16 /****************************表达x所需要的最少位数******************************/ 17 int howManyBits(int x) { 18 int bit_16, bit_8, bit_4, bit_2, bit_1, result; 19 int k = x >> 31; 20 int temp = x ^ k;
//x为正,temp = x;x为负,temp = ~x 21 int isZero = (!!(temp << 31)) >> 31;
//x = 0或x = -1时,temp = 0,isZero = 0...0;否则isZero = 1...1 22 bit_16 = (!!(temp >> 16)) << 4; 23 temp = temp >> bit_16; 24 bit_8 = (!!(temp << 8)) << 3; 25 temp = temp >> bit_8; 26 bit_4 = (!!(temp << 4)) << 2; 27 temp = temp >> bit_4; 28 bit_2 = (!!(temp << 2)) << 1; 29 temp = temp >> bit_2; 30 bit_1 = temp >> 1; 31 result = bit_16 + bit_8 + bit_4 + bit_2 + bit_1 + 2;
//真正位数为bit_16 + ... + bit_1 + 1,再加符号位一位 32 return (!isZero) | (result & isZero); 33 } 34 35 /************************************逻辑右移*************************************/ 36 int logicshift(int x, int n) 37 { 38 int temp = ~(1 << 31); 39 temp = ((temp >> n) << 1) + 1; //生成掩码0...01...1(前面为n个0) 40 return (x >> n) & temp; 41 } 42 43 /*************************类似于c语言中的x ? y : z**********************************/ 44 int conditional(int x, int y,int z) 45 { 46 int temp = (~(!x)) + 1; //要在return中完成,必须生成x,y的掩码 47 return (temp & z) | ((~temp) & y); //当x = 0时,temp = 1...1;当x != 0时,temp = 0...0 48 } 49 50 /*********************************** x/ 2^n *****************************************/ 51 int divpwr2(int x, int n) 52 { 53 int temp = (1 << n) + (~0); //temp为baising(偏置),1...1(共n个1) 54 return (x + ((x >> 31) & temp)) >> n; //只有负数才要加偏置,所以temp要与符号位相与 55 } 56 57 /****************************** x < y ? ***********************************/ 58 int isLessOrEqual(int x, int y) 59 { 60 int signx = x >> 31; 61 int signy = y >> 31; 62 int signEqual = (!(signx ^ signy) & ((x + (~y)) >> 31));//符号位不同时,做差 63 int signDiffer = signx & (!signy); //符号位相同,直接比较符号位 64 return signEqual | signDiffer; 65 } 66 67 /**********************操作数更小的版本**************************/ 68 int isLessOrEqual_2(int x, int y) 69 { 70 int not_y = ~y; 71 return ((((x + not_y) & (x ^ not_y)) | (x & not_y)) >> 31) & 1; 72 // x-y-1<0 <----------x,y不同号------>x为负,y为正,才为正 73 } 74 75 /****************************不用负号得到-x*********************************/ 76 int negate(int x) 77 { 78 return ~x + 1; //按位取反,末位加一 79 } 80 81 /**********************返回最小的补码***************************************/ 82 int tmin(void) 83 { 84 return 1 << 31; 85 } 86 87 /*************************只用~ 和 | 实现x&y*****************************/ 88 int bitAnd(int x, int y) 89 { 90 return ~(~x | y); //摩根律 91 } 92 93 /**************************从字x中取出第n个字节*********************************/ 94 int getByte(int x, int n) 95 { 96 return (x >> (n << 3)) & 0xff; //是从0开始数的 97 } 98 99 /*********************************计算x中1的数目*********************************/ 100 int bitCount(int x) 101 { 102 int result; 103 int tmpmark1 = 0x55 + (0x55 << 8); //最大0xff 104 int mark1 = tmpmark1 + (tmpmark1 << 16); 105 int tmpmark2 = 0x33 + (0x33 <<8); 106 int mark2 = tmpmark2 + (tmpmark2 << 16); 107 int tmpmark3 = 0x0f + (0x0f << 8); 108 int mark3 = tmpmark3 + (tmpmark3 << 16); 109 int mark4 = 0xff + (0xff << 16); 110 int mark5 = 0xff + (0xff << 8); //以上生成5个掩码 111 112 result = (x & mark1) + ((x >> 1) & mark1); 113 result = (result & mark2) + ((result >> 2) & mark2); //这两个由于进位问题,不能先加再与 114 result = (result + (result >> 4)) & mark3; //分治 115 result = (result + (result >> 8)) & mark4; 116 result = (result + (result >> 16)) & mark5; 117 return result; 118 } 119 120 /***************************计算uf/2*********************************/ 121 unsigned float_half(unsigned uf) 122 { 123 unsigned s = uf & 0x80000000; 124 unsigned exp = uf & 0x7f800000; 125 int lsb = ((uf & 3) == 3); //判断frac最后两位是否为11 126 if (exp == 0x7f800000) 127 return uf; 128 else if (exp <= 0x800000) 129 return s | (((uf ^ s) + lsb) >> 1); //uf^s将符号位置零,uf^s = frac + exp末位 130 else 131 return uf - 0x800000; //整体思路就是模拟 132 } 133 134 /****************************计算(float)x***********************************/ 135 int float_f2i(unsigned uf) 136 { 137 int abs; 138 int sign = uf >> 31; 139 int exp = (uf >> 23) & 0xff; 140 int frac = uf & 0x007fffff; 141 if (exp < 0x7f) return 0; 142 if (exp > 157) return 0x80000000; //Tmax = 2^31 -1 143 144 abs = ((frac >> 23) + 1) << (exp - 127); //模拟 145 if (sign) 146 return -abs; 147 else 148 return abs; 149 } 150 151 /****************************计算2*f***************************************/ 152 unsigned float_twice(unsigned uf) 153 { 154 int result; 155 int exp = uf & 0x7f800000; 156 int frac = uf & 0x7fffff; 157 if (exp == 0x7f800000) 158 return uf; 159 else if (exp == 0) 160 frac = frac << 1; //frac也可用uf代替,因为此时frac = uf 161 else 162 exp = exp + 0x800000; 163 result = (uf & 0x80000000) | exp | frac; 164 return result; 165 }