CSAPP data实验
前前后后做了大概一个星期,大致是周末多弄点,平时少弄点。最近疫情迭起又搞得图书馆的卷王和我抢自习室,然后又是PCR啥的打乱了正常生活秩序,希望疫情早日消失吧。
其他的函数都还好,就这个howmanybits搞得我焦头烂额。
排核酸的时候我在想,睡觉的时候我在想,怎么也找不出在90次位操作以内的解法,离谱,还是我太菜了。
简单记下当初的想法:
- bitXor
用取反和位与实现异或,数字逻辑题
记 横杠 为[]
x ^ y
= x[y] + [x]y
= [[x[y]][[x]y]] (德摩根律)
[num] = ~num
故有 x ^ y = ((x & (~y)) & ((x) & y)))
level1, 问题不大
-
tmin
题目假定了是32位,常数在0~256范围内就行,那么直接 1<<31 就行了
暂时没想出通用于16位int的方法 -
isTmax
如果是tmax,加1就和tmin异或得0了,结果再非一下 -
allOddBits
符合这个条件的只有一个数,用给定的操作和范围内的常数把这个数得到,
然后异或一下就差不多了 -
negate
书上给过的补码规律: -x = ~x + 1 -
isAsciiDigit
这个是用位运算判断一个数是否在一个给定的范围……
首先确定高位都是0,然后确认低位第二个字节是0011,最后是画的卡诺图把低4位情况判断一下
最后用或非四个判断结果作为返回值 -
conditional
用!x把判断变量的范围限制在0或1,然后negate一下作掩码
从这里开始画风开始变化
8. isLessOrEqual
按两个数的符号位分情况讨论:
(1) x是正数, y是负数
(2) x是负数, y是正数
(3) x是正数, y是正数
(4) x是负数, y是负数
(1)(2)情况根据符号位可以直接得结果:
一个变量记一下是不是这种情况,另一个记一下是(1)还是(2)
(3)(4)情况可以直接减而不用担心溢出
然后和0异或就差不多了
9.logicalNeg
这个是灵光一现,不用32位逐位或一遍
如果x非0,那么x和-x总有一个符号位是1
用这个判断就行了
10. howManyBits
(暂时没想出来)
90次运算,对应30位 * 3次
至少要用1位,最后一位不用判断
符号位也要通过某种手段处理
剩下30位每位也才允许3次操作
(1)想过异或来帮我判断:
x左移一位,然后和x异或,出来的结果中
只要知道第一个1出现的位置,就能知道答案
但是要>>,!,+ 31次,超了
而且需要!两次加起来……
(2)想过直接右移判断
每次右移,非0就加1,直到数为0或-1为止
判断数为0或-1成本太大
而且还是需要非两次
而且还需要重复31次
G
就算只有正数,也想不到……
11-12-13. float运算
这里要求松多了,几乎可以用除函数调用、类型转换之外的任意操作,包括条件判断
所以主要就是把符号位、阶码、小数部分取出来,然后分情况细致讨论即可,和howmanybits比起来是毛毛雨啦