The purpose of this assignment is to become more familiar with bit-level representations of integers and floating point numbers. You’ll do this by solving a series of programming “puzzles.” Many of these puzzles are quite artificial, but you’ll find yourself thinking much more about bits in working your way through them.
/* * conditional - same as x ? y : z * Example: conditional(2,4,5) = 4 * Legal ops: ! ~ & ^ | + << >> * Max ops: 16 * Rating: 3 */ intconditional(int x, int y, int z){ x = !!x; x = ~x + 1; return (x&y)|((~x)&z); }
//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 */ unsignedfloatScale2(unsigned uf){ intexp = (uf&0x7f800000)>>23; int sign = uf&(1<<31); if(exp==0) return uf<<1|sign; if(exp==255) return uf; exp++; if(exp==255) return0x7f800000|sign; return (exp<<23)|(uf&0x807fffff); }
本函数要求使用 unsigned int 来表示float,并计算2float,首先,明确unsigned int 在 IA32 计算机中的位数,一共32位,那么sign占一位,exp占8位,M占23位。那么对于2f来说,只要修改exp就行了。但是存在特殊情况,当exp==0时,是非规格化的情况,直接M<<1就行;当exp==0xFF时,代表NaN,直接返回。再对exp++,就可以。在增加过后,还需要检查exp是否正确,当exp==0xFF,返回原符号的无穷大。否则,返回指数加一以后的数。
/* * 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 */ intfloatFloat2Int(unsigned uf){ int s_ = uf>>31; int exp_ = ((uf&0x7f800000)>>23)-127; int frac_ = (uf&0x007fffff)|0x00800000; if(!(uf&0x7fffffff)) return0;
/* * 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 */ unsignedfloatPower2(int x){ int INF = 0xff<<23; intexp = x + 127; if(exp <= 0) return0; if(exp >= 255) return INF; returnexp << 23; }
1. Running './dlc -z' to identify coding rules violations.
2. Compiling and running './btest -g' to determine correctness score. gcc -O -Wall -m32 -lm -o btest bits.c btest.c decl.c tests.c btest.c: In function ‘test_function’: btest.c:332:23: warning: ‘arg_test_range[1]’ may be used uninitialized in this function [-Wmaybe-uninitialized] 332 | if (arg_test_range[1] < 1) | ~~~~~~~~~~~~~~^~~
3. Running './dlc -Z' to identify operator count violations.
4. Compiling and running './btest -g -r 2' to determine performance score. gcc -O -Wall -m32 -lm -o btest bits.c btest.c decl.c tests.c btest.c: In function ‘test_function’: btest.c:332:23: warning: ‘arg_test_range[1]’ may be used uninitialized in this function [-Wmaybe-uninitialized] 332 | if (arg_test_range[1] < 1) | ~~~~~~~~~~~~~~^~~
5. Running './dlc -e' to get operator count of each function.