Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 
邓博昊 4d99345b9e Fix Bugs před 1 rokem
..
Driverhdrs.pm Create A Repo před 1 rokem
Driverlib.pm Create A Repo před 1 rokem
Makefile Finish LogicalNeg and Update Makefile před 1 rokem
README Fix Bugs před 1 rokem
bits.c Fix Bugs před 1 rokem
bits.h Create A Repo před 1 rokem
btest.c Create A Repo před 1 rokem
btest.h Create A Repo před 1 rokem
decl.c Create A Repo před 1 rokem
dlc Create A Repo před 1 rokem
driver.pl Create A Repo před 1 rokem
fshow.c Create A Repo před 1 rokem
ishow.c Create A Repo před 1 rokem
tests.c Create A Repo před 1 rokem

README

1. bitXor思路

根据德摩根定律,A^B = (A&~B)|(~A&B)

2. tmin思路

最小的INT类即首位1,末31位全为0,故TMIN = 0x1<<31

3. isTmax思路

设置掩码y = 0x7fffffff
构造掩码方式为 y = (0x7f<<24)+(0xff<<16)+(0xff<<8)+0xff
x^y只有在x = Tmax时才为0,其余情况非0
取反返回即可

4. allOddBits思路

设置掩码y = 0xaaaaaaaa
构造掩码方式为 y = (0xaa<<24)+(0xaa<<16)+(0xaa<<8)+0xaa
由于只看奇数次幂
故得过滤掉偶数次幂,即x&y使得偶数次幂均为0,奇数次幂不变
随后 (x&y)^y即可
只有奇数次幂全为1才可输出为0,其余非0
取反返回即可

5. negate思路

补码规则 负数取反加一即可

6. isAsciiDigit思路

上界为0x39 下届为0x30
各取补码
将x各与其补码相加
结果符号位为0 表示x大于等于该界限
结果符号位为1 表示x小于该界限
故为了满足 0x30 <=x <=0x39
则上界调整为0x3a
提取出符号位右移31位即可
满足结果为1,则{![(~down+1+x)>>31]}&[!!(~up+1+x)>>31]

7. conditional思路

x为非0输出y
x为0输出z
则令x = !!x;x = ~x+1
当x为非0时,最终x全为1
当x为0时,最终x全为0
输出(x&y)|(~x&z)即可

8. isLessOrEqual思路

取y的补码
x+(~y+1)
此时x大于等于y,结果符号位为0
x小于y,结果符号位为1
为了变成小于等于,式子改为x+(~y+1)-1
右移31位取反再取反返回即可

9. logicalNeg思路

利用0的补码仍然为0的特点
x = x|(~x+1)
显然对于0,最高位为0
对于非0,其最高位必定1(正数补码为负数,负数补码为正数,取并必定有1)
右移31位提取最高位即可
为了让0输出1,非0输出0,再加1返回

10. howManyBits思路

运用二分查找的思想
为了方便查找,应让负数也变成符号位为0,即应取反
x = ((~(x>>31))&x)|(x>>31&~x) 即可完成该操作,正数保持原样,负数取反

二分,查找有没有超过16位
tf = !!(x>>16) 如果小于等于16位,则为0,否则为1

如果超过了,二分超过的16位,没超过,二分没超过的16位
int b16 = tf << 4 长度超过16位,记录值b16为16,否则为0,代表至少16位
x = x>>b16 右移动b16位,超过16位则探讨16位以上的,少于16位则探讨16位以下的

b8 b4 b2 b1 同理

值得注意的是
当经过x = x>>b1操作后
x只会剩下一个原表达式中的数字
应该令b0 = x,如果该数字为1,则b0为1,否则为0

最终位数结果为 b16+b8+b4+b2+b1+b0+1 正数多一位补码最高位,负数因为取反未+1,理应再加1,故两个输出表达式一致

11. floatScale2思路

unsigned sign = (0x80<<24)&uf;
unsigned exp = ((0x7f<<24)+(0x80<<16))&uf;
unsigned frac = ((0x7f<<16)+(0xff<<8)+0xff)&uf;
使用三个掩码分别提取出sign exp frac
应注意非规格化数
if(exp == ((0x7f<<24)+(0x80<<16)))
return uf; //如果是exp全为255,frac全是0就是无穷,不是就是NaN,都直接return
if(exp == 0x0){
if(frac == 0x0)
return uf; //exp全为0,frac全为0,则为0,0*2=0,原样不动
return (frac<<1)|sign|exp;//exp全为0,frac不全为0,注意到非规格化极小和规格化之间是连续的,即frac第一位为1时,左移会把exp变为非全0,回到规格化
}

剩下的情况就是规格化数
乘以2后exp应多加一,加完后按原来float数规则复原即可
return (exp+(0x80<<16))|sign|frac;

12. floatFloat2Int思路

使用三个掩码提取出各部分,为了方便计算,sign和exp复原到最简单的int
unsigned sign = ((0x80<<24)&uf)>>31;
unsigned exp = (((0x7f<<24)+(0x80<<16))&uf)>>23;
unsigned frac = ((0x7f<<16)+(0xff<<8)+0xff)&uf;

同时再定义一个不满足题干要求时应输出的数值
unsigned notpermit = 0x80 << 24;

对于常规数,根据规则,应为1+frac代表的小数
复原至float的frac
unsigned base = (frac+(0x80<<16))

同时,2的幂是经过偏移后的,求出该幂,并应对后面base左移需求,额外再减23
int bias = (exp-127)-23;//真实需要左移的

解析sign,让其在乘法时正确使用
if(sign==0)
sign = 1;
else
sign = -1;

排除非规格数
if(exp == 255)
return notpermit;//足够大
if(exp == 0)
return 0;//足够小

如果bias <= 0 则右移,否则左移
base有效数字只有24位,故还应判断bias是否小于等于24 如果小于,显然已经偏移到足够小了,换成int一定会是0,故设置bias为恒定-24即可
如果bias >0 则左移
当bias>=9时,将超过int表达范围,此时返回规定的数即可
综上,为
if(bias <=0){
if(bias<=-24)
bias = -24;
return sign*(base>>(-bias));
}
else{
if(bias>=9)
return notpermit;
return sign*(base<<bias);
}