整数位操作实验
实验目的
对整数的二进制表示及操作更为熟悉
实验内容
- 本实验由一组程序实现问题构成
- 仅利用位操作符来实现特定的功能
- 位操作符:! ~ & ^ | + << >>
- 特定的功能:大小比较、条件判断、浮点乘法等
- 每个题目可能包含着一些特别设定的规则
- 运算符的数量(见分发布的代码中函数注释)
- 可使用的常量需在8比特可表述的范围内,即0x00 (0)到0xFF (255)
实验步骤
bitXor
-
按照ppt上打就行。
int32_t bitXor(int32_t x, int32_t y) { int32_t res =~ (~(x & ~y) & ~(~x & y)); return res; }
Tmin
-
1左移31位即可。
int32_t tmin(void) { int32_t res = 1 << 31; return res; }
isTMax
-
由ppt得
(!(~(x+x+1)))
-
排除
0xffffffff
即判断(x+1)!=0
,可用!!(x+1)
-
用
&
将二者并起来就行。int32_t isTmax(int32_t x) { int32_t res = (!(~ (x+x+1)))&(!!(x+1)); return res; }
allOddBits
-
获得
0x55555555
可用移位操作 -
与x进行
|
,符合条件,返回0xffffffff
-
判断
0xffffffff
,如果x=0xffffffff
,则!~(x)=1
,否则为0。int32_t allOddBits(int32_t x) { int32_t res =!(~(x | ((0x55<<24)+(0x55<<16)+(0x55<<8)+0x55))); return res; }
Negate
-
取反加一
int32_t negate(int32_t x) { int32_t res = ~x+1; return res; }
isAsciiDigit
-
(x+(~0x30+1))
即为(x-0x30)
,右移31位得到符号位,若在范围内,返回0,再取!,得1. -
!((0x39+(~x+1)))>>31
同理 -
二者取
&
即可int32_t isAsciiDigit(int32_t x) { int32_t res = !((x + (~ 0x30+1))>>31) & !((0x39 + (~ x+1))>>31); return res; }
Conditional
-
现将x转化为0或1,用
(!!x)
,0返回0,非0返回1。 -
1取反加1得
0xffffffff
,0取反加1得0x00000000
,则mask=~(!!x)+1
,相反,mask2=~(mask1)
。 -
使用ppt的公式代入即可
int32_t conditional(int32_t x, int32_t y, int32_t z) { int32_t res = ((~(!!x)+1) & y) | (~(~(!!x)+1) & z); return res; }
isLessOrEqual
-
由ppt可知,得分同号和异号的情况,取符号
x_sgin=x>>31,y_sign=y>>31
。 -
可以使用类似函数7的公式
mask1 & y | mask2 & z
。 -
若同号,即
~(x_sign^y_sign)=0xffffffff
,!!((x+~y+1)>>31)
在x>=y时为0,二者取&
得同号情况 -
若异号,即
~(x_sign^y_sign)=0x0000000
,!!(s_sign)
在x>y时为0。 -
若相等,即
!!(x+~y+1)=1
-
3.4.5.取
|
得结果。int32_t isLessOrEqual(int32_t x, int32_t y) { int32_t x_sign = x>>31; int32_t y_sign = y>>31; int32_t res = (~(x_sign ^ y_sign) & !!((x+~y+1)>>31)) | ((x_sign ^ y_sign) & !!(x_sign)) | !(x+~y+1); return res; }
logicalNeg
-
由ppt可知,x和-x符号相同为0,返回1,排除
0x8000000
。 -
x_sign^neg_x_sign+1 = 1
。 -
若是
x=0x80000000
,即x_sign+1 = 0
,x_sign^neg_x_sign+1
和x_sign+1
取&
会返回0,而x=0
的时候返回1。这样就排除了0x80000000
。int32_t logicalNeg(int32_t x) { int32_t x_sign = x>>31; int32_t neg_x = ~x+1; int32_t neg_x_sign = neg_x>>31; int32_t res = ((x_sign^neg_x_sign)+1) & (x_sign+1); return res; }
howManyBits
-
分析:即正数求最前面的1的位置加1,负数求最前面的0的位置,可对负数取反,便和正数一样求解。
-
使用
Condition()
函数的思想,令x=(x_sign & ~x) | (~x_sign & x)
,可对负数取反。 -
如果一次右移一位,操作符过多。可以使用二分法思想,将x右移16位,如果x不为0,则说明至少16位前有1,将x的值改为x>>16,结果加上16,否则移动0位。一直右移8,4,2,1位,直到移动1位。最后如果x=1,结果加上1;x=0,结果加上0。最后结果加1(符号位)。
int32_t howManyBits(int32_t x) { int32_t res,x_sign,b1,b2,b3,b4,b5; x_sign = x>>31; x = (x_sign & ~x) | (~x_sign & x); b1 = !!(x>>16)<<4; x = x>>b1; b2 = !!(x>>8)<<3; x = x>>b2; b3 = !!(x>>4)<<2; x = x>>b3; b4 = !!(x>>2)<<1; x = x>>b4; b5 = !!(x>>1); x = x>>b5; res = b1+b2+b3+b4+b5+x+1; return res; }
实验结果和总结
运行结果截图
实验总结
- 判断一个数是否为0,
!x
;判断一个数是否不为0,!!x
。 - 判断一个数是否为-1,
!(x+1)
或者!~x
。 - 8字节的数构造32字节的数可以用左移和加法。
- 判断正负数,利用符号位,即
x>>31
,正数结果为0x00000000
,负数结果为0xffffffff
。 - 减法可用加上一个数的负数实现,即取反加一。
- 三元运算符
x?y:z
的实现,使用格式res = mask1 & y | mask2 & z
,其中mask2=~mask1
,当x
不为0时mask1
取0xffffffff
,x
为0时mask1
取0x00000000
。 - 判断两个数
a
,b
是否相等使用异或操作!(a^b)
,如果相等返回1,不等返回0。