Datalab
何睿 21302010005
1、bitXor:
x & y :找出x,y同为1的位,记为1
~x & ~y:找出x,y同为0的位,记为1
(x & y) | (~x & ~y) :找出x,y相同的位,记为1(异或是记为0)
~(x & y) | (~x & ~y):满足异或运算
由于只能用 ~ 和 & ,将括号拆开后:~(x & y) & (x & ~y)
2、tmin:
补码最小的整形:首位为1,其余位均为0,共32位。
将1左移31位即可。
3、isTmax:
最大数Tmax:首位为0,其余位均为1,共32位。
将Tmax加1后,会变成首位为1,其余位均为0,共32位。
两者 异或 后,得到 32位全1,取反 得到 32位全0。
! ( ~( x ^ (x + 1) ) ) 满足Tmax输出1,不满足输出0。
但 -1 也能满足该式,因为 -1 是32位全1,加1后溢出,变为32位全0。
所以还需要排除 x 为 -1的情况,即 !!(x + 1) 。
两个条件需均成立:用&连接,可以符合最终要求。
4、allOddBits:
先排除偶数位的影响:
创造一个常数allodd,使得奇数位均为1,偶数位均为0。
因为常数只有8位,所以需要左移运算:
allodd = (0xaa) + (0xaa << 8) + (0xaa << 16) + (0xaa << 24)
将x与allodd做 & 运算,从而得到一个新的常数x_odd,满足:
x_odd与x的奇数位相同,而x_odd的偶数位都为0。
再将x_odd 与 allodd 异或,检查是否奇数位都为1。
最后,! (x_odd ^ allodd) 输出结果。
5、negate:
相反数:取反加1
6、isAsciiDigit:
先右移3位来判断原数字的前几位是否为 0x6 (即判断“0……0110***”):
! ( ( x >> 3 ) ^ 6 ) (包括了0x30 到 0x37)
再额外判断是否为 0x38 或 0x39 :
! ( x ^ 0x38 ) ! ( x ^ 0x39 )
三个条件满足其一即可:用异或连接
( ! ( (x >> 3) ^ 6) ) ^ ( ! (x ^ 0x38) ) ^ ( ! (x ^ 0x39) )
7、conditional:
定义一个变量flag 为 ~ (!!x) + 1:
!!x:x为0,值为0; x非0,值为1。
flag:x为0,32位全0; x非0,32位全1。
( flag & y ) | ( ~flag & z ):
若x为0,flag为0,(flag & y) 为 0,( ~flag & z ) 为z,两者取 | ,结果为z。
若x非0,flag为-1,(flag & y) 为 y,( ~flag & z ) 为0,两者取 | ,结果为y。
满足:x ? y : z
8、isLessOrEqual:
先取x,y的符号位:x_sign = (x >> 31) & 1; y_sign = (y >> 31) & 1;
再求x与y的差值:d_val = x + (~y + 1);
再判断差值正负(<=返回1,>返回0):
d_judge = !((d_val & (1 << 31)) ^ (1 << 31)) | !(d_val ^ 0) 其中:
(d_val & (1 << 31)) ^ (1 << 31) 判断d_val首位0或1(即差值正负):
!(d_val ^ 0) 判断d_val 是否为0(即两数是否相等)
最后返回( ! ( ~x_sign & y_sign ) ) & ( ( x_sign & ~y_sign ) | d_judge )
! ( ~x_sign & y_sign ) 只有同号或x负y正,返回1
( x_sign & ~y_sign ) | d_judge 同号再判断大小,小于等于返回1
需同时满足两条件,用 & 连接。
9、logicalNeg:
x与其相反数取 | ,再右移31位,保留符号位。
只有x为0时,结果为0;x非0,结果为-1.
再对其加1,满足 !运算。
10、howManyBits:
若x为正,从左到右找到第一个1,再加1就是所求的位数。
若x为负,取反后按上述方式求(不需再加1)
先找到最高位:sign = x >> 31
转化为正数:x = (sign & ~x) | (~sign & x)
然后用二分法查找:
b16 = (!!(x >> 16)) << 4; 判断高16位是否有1,如果有,将变量赋值为16
x = x >> b16; 如果有1,右移16位,继续查找。
后续同理,查找前8位,前4位,……,直至完全查找。
最后返回:b16 + b8 + b4 + b2 + b1 + b0 + 1(最后的+1是符号位), 就是所求位数。
11、floatScale2:
先找到阶码:exp = (uf >> 23) & 0xff; 和符号位:sign = uf & (1 << 31);
如果为非规格化数,即阶码为0时,uf小于1,可直接左移乘二。
如果为规格化数,即阶码不为 0时,只需将阶码加1 即可。
但是若加1后溢出,则需要返回 0x80000000
12、floatFloat2Int:
计算阶码 ((uf >> 23) & 0xff);与尾数:frac = (uf & 0x7fffff) | 0x800000;
记 exp = ((uf >> 23) & 0xff) - 127;
若exp小于 0,则f的绝对值一定小于 1,直接返回 0
若exp大于 31,发生溢出,返回 0x80000000
其余情况,将小鼠部分转化为整数,判断溢出:
与原符号相同则直接返回,不同则:
结果为负,溢出
结果为正,则需要返回其相反数
13、floatPower2:
将exp加上x即可,判断是否溢出。