DATA LAB
代码
//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) {
int z = ~(x & y);
int a = ~(x & z);
int b = ~(y & z);
return ~(a & b);
}
/*
* tmin - return minimum two's complement integer
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 4
* Rating: 1
*/
int tmin(void) {
return 1 << 31;
}
//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)) & (!!(x + 1)));
}
/*
* 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 msk = 0xAA;
msk |= msk << 4;
msk |= msk << 8;
msk |= msk << 16;
return !((x & msk) ^ msk);
}
/*
* negate - return -x
* Example: negate(1) = -1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 5
* Rating: 2
*/
int negate(int x) {
return ~x + 1;
}
//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) {
int lb = 0x30, ub = 0x39;
int a = !(x >> 6);
int b = !((x + (~lb + 1)) >> 31);
int c = !((ub + (~x + 1)) >> 31);
return a & b & c;
}
/*
* 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) {
int msk = !x;
msk |= msk << 1;
msk |= msk << 2;
msk |= msk << 4;
msk |= msk << 8;
msk |= msk << 16;
return (z & msk) + (y & ~msk);
}
/*
* 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) & 1;
int sy = (y >> 31) & 1;
int diff = y + (~x + 1);
int sd = (diff >> 31) & 1;
return (sx & !sy) | (!(sx ^ sy) & !sd);
}
//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;
}
/* 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 mask = x >> 31;
int u = x ^ mask;
int n = 0;
int bit;
int zero;
int mask_sel;
bit = !!(u >> 16); n += bit << 4; u >>= bit << 4;
bit = !!(u >> 8); n += bit << 3; u >>= bit << 3;
bit = !!(u >> 4); n += bit << 2; u >>= bit << 2;
bit = !!(u >> 2); n += bit << 1; u >>= bit << 1;
bit = !!(u >> 1); n += bit; u >>= bit;
zero = !u;
mask_sel = ~zero + 1;
return ((n + 2) & ~mask_sel) | (1 & mask_sel);
}
//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 sign = uf & 0x80000000;
unsigned exp = (uf >> 23) & 0xff;
unsigned frac = uf & 0x7fffff;
if (exp == 0xff) return uf;
if (exp == 0) {
frac <<= 1;
if (frac & 0x800000) {
exp = 1;
frac &= 0x7fffff;
}
return sign | (exp << 23) | frac;
}
exp += 1;
if (exp == 0xff) return sign | 0x7f800000;
return sign | (exp << 23) | frac;
}
/*
* 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) {
int sign = uf >> 31;
int exp = (uf >> 23) & 0xff;
unsigned frac = uf & 0x7fffff;
int E = exp - 127;
unsigned mant = (1u << 23) | frac;
unsigned abs;
if (exp == 0xff) return 0x80000000u;
if (exp == 0) return 0;
if (E < 0) return 0;
if (sign == 0) {
if (E >= 31)return 0x80000000u;
if (E < 23) abs = mant >> (23 - E);
else abs = mant << (E - 23);
return abs;
}
else {
if (E > 31) return 0x80000000u;
if (E < 23) abs = mant >> (23 - E);
else abs = mant << (E - 23);
if (abs > 0x80000000u) return 0x80000000u;
return -abs;
}
}
/*
* 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 < -149) return 0;
if (x > 127) return 0x7f800000u;
if (x >= -126) return (x + 127) << 23;
return 1u << (x + 149);
}
总结
1. 当前完成状态
| 检查项 |
结果 |
说明 |
btest 正确性测试 |
36/36 |
所有函数在测试用例下结果正确 |
dlc 规则检查 |
通过 |
符合 Data Lab 的操作符和语法限制 |
当前代码已经同时通过 btest 和 dlc,可以作为规则检查通过版继续复盘和提交。
2. 整数题核心思路
| 函数 |
核心技巧 |
关键点 |
bitXor |
德摩根律 |
用 ~ 和 & 拼出异或 |
tmin |
最高位置 1 |
1 << 31 得到补码最小值 |
isTmax |
TMax + 1 == TMin,且 TMax ^ TMin == -1 |
额外排除 x == -1 |
allOddBits |
构造 0xAAAAAAAA 掩码 |
检查所有奇数位是否都为 1 |
negate |
补码取负 |
-x == ~x + 1 |
isAsciiDigit |
上下界检查 |
判断 0x30 <= x <= 0x39 |
conditional |
全 0 / 全 1 掩码选择 |
用掩码模拟 x ? y : z |
isLessOrEqual |
分类讨论符号 |
异号时看符号,同号时看 y - x |
logicalNeg |
0 和非 0 的符号特征 |
非 0 时 `x |
howManyBits |
二分查找最高有效位 |
先把负数变成对应的非负形态,再定位最高位 |
3. 浮点题核心思路
| 函数 |
分类方式 |
关键处理 |
floatScale2 |
按 exp 分为 NaN/Inf、非规格化数、规格化数 |
非规格化数左移 frac,规格化数 exp + 1 |
floatFloat2Int |
根据 exp 得到真实指数 E = exp - 127 |
E < 0 返回 0,溢出/NaN/Inf 返回 0x80000000u |
floatPower2 |
根据指数范围分为太小、非规格化、规格化、太大 |
x < -149 为 0,x > 127 为 +INF |
浮点题的主线是固定的:
uf = sign | exp | frac
sign = uf >> 31
exp = (uf >> 23) & 0xff
frac = uf & 0x7fffff
然后按 exp 分类:
exp |
含义 |
0 |
零或非规格化数 |
1..254 |
规格化数 |
255 |
NaN 或无穷 |