前言

《深入理解计算机系统》实验一Data Lab下载和官方文档机翻请看:
https://blog.csdn.net/weixin_43362650/article/details/122847056

我觉得这个文档对整个实验很有帮助。

本播客的实验一不是官方的实验一,是学校发的所以一些函数不太一样,仅供参考。
有需要的可以在这里下载:《深入理解计算机系统》CS:APP实验一Data Lab(非官方版)

实验任务

本实验完成的函数如下:

位操作

本题分数函数名功能约束条件最多操作符数
1isZero判断变量x是否为0。如果为0,则返回1;否则,返回0。仅可以使用以下操作符: ! ~ & ^ | + << >>2
1specialBits构建0xffca3fff,并返回。! ~ & ^ | + << >>3
1upperBits根据输入的变量n,构建一个高n位为1其他位为0数,并返回该值。注:0<= n <=32~ & |10
1bitMatch构建一个比特序列(int型),构成规则如下:如果x和y在某一个bit位置的值相同,则此序列的相应位置为1,否则该位置值为0。~ & |14
1bitOr计算按比特或(x | y),并将计算结果返回。~ &8
4logicalNeg使用位操作符实现逻辑非(!x)操作,并将取逻辑非之后的结果返回。~ & ^ | + << >>12
4bitParity如果x中包含奇数个0,则返回1;否则返回0。! ~ & ^+ << >>
2byteSwap将x的第n字节和第m字节交换,0 <= n <= 3, 0 <= m <= 3,然后将交换后的值返回。! ~ & ^ | + << >>25
2getByte提取x的第n个字节。0 <= n <= 3 (0代表最最低为字节,3代表最高位字节),并将其返回。! ~ & ^ | + << >>6
2oddBits返回一个32bit数,这数的所有第奇数个bit位置的值为1。! ~ & ^ | + << >>8
3replaceByte将x的第n个字节用 c 进行替换,0 <= n <= 3, 0 <= c <= 255并将替换后的结果返回。! ~ & ^ | + << >>10
3rotateLeft将x向左循环移位n个bit。循环移位是指左边移除去的比特自动填充到右边空出的位置上。 0 <= n <= 31,并将循环移位后的值返回。! ~ & ^ | + << >>25

补码运算:

本题分数函数名功能约束条件最多操作符数
2negate将输入参数x的值取相反数,返回-x。! ~ & ^ | + << >>5
4absVal计算变量x的绝对值,并将其绝对值返回。! ~ & ^ | + << >>10
3isGreater如果x > y,则返回1,否则返回0。! ~ & ^ | + << >>24
2isNegative如果x < 0,返回1;否则返回0。! ~ & ^ | + << >>6
4isPower2如果x是2的整数次幂,则返回1;否则返回0。! ~ & ^ | + << >>20
3addOK如果x+y没有溢出,则返回1;否则返回0。! ~ & ^ | + << >>20
3subtractionOK如果x-y没有溢出,则返回1;否则返回0。! ~ & ^ | + << >>20

浮点数:

本题分数函数名功能约束条件最多操作符数
2floatAbsVal通过bit级操作返回一个float型浮点数的绝对值。如果输入参数为NaN,则直接返回输入参数的原值。可以使用任何的操作符,包括||和&&。也可以使用if,while。10
2floatIsEqual判断两个浮点数是否相等,如果相等则返回1,否则返回0。如果输入参数中含有NaN,则返回0。注:+0和-0被当作相等的情况对待。可以使用任何的操作符,包括||和&&。也可以使用if,while。25

isZero

判断变量x是否为0。如果为0,则返回1;否则,返回0。

/*
 * isZero - returns 1 if x == 0, and 0 otherwise 
 *   Examples: isZero(5) = 0, isZero(0) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 2
 *   Rating: 1
 */
int isZero(int x) {
/*
  没啥好说的。x^0。
  x=0时,x^0=0。
  x!=0时,x^0=1。
  在取非(!)
*/
  return !(x^0);
}

negate

将输入参数x的值取相反数,返回-x。

/* 
 * negate - return -x 
 *   Example: negate(1) = -1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 5
 *   Rating: 2
 */
int negate(int x) {
/*
  没啥好说的。
  补码与原码取反加1
*/
  return ~x + 1;
}

specialBits

构建0xffca3fff,并返回。

/* 
 * specialBits - return bit pattern 0xffca3fff
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 3
 *   Rating: 1
 */
int specialBits(void) {
/*
  因int取值为0~255,
  刚开始的思路是创建两个变量,使用位移构造出ca3。
  0xff...fff肯定是要取反获得的了,所以刚开始就构造0xca3的反码0x35c,
  在位移使(0x0035c000),取反即完成。
  所以可得(~((0x35<<16)|(0xc0<<8))=0xffca3fff。
  发现使用了4op,不合题意。

  分析有没有可以优化的,
  取反~占1op,构造0x35c"要对0x35使用位移1op,合并成0x35,0xc也要1op,位移到正确的位置1op。
  想到能不能使用加法来构造0x35c这样位移+合并的2op就变成加法的1op。
  发现int+int到不了0x35c,不过这是一个很好的思路,用其他的办法来构造0x35c
  0x35c二进制为0011 0101 1100,发现低2位和高2位都是0,可以吧0x35c>>2=1101 0111=0xD7
  所以0x35c可以表示为0xD7<<2,很好,在把0x35c位移到合适的位置,即
  0xD7<<2<<12=0xD7<<14
  取反即~(0XD7<<14)返回0xffca3fff

*/
  //0xD7<<2<<12, D7<<2 = 35c,
  return ~(0XD7<<14);
}

upperBits

根据输入的变量n,构建一个高n位为1其他位为0的数,并返回该值。注:0<= n <=32

/* 
 * upperBits - pads n upper bits with 1's
 *  You may assume 0 <= n <= 32
 *  Example: upperBits(4) = 0xF0000000
 *  Legal ops: ! ~ & ^ | + << >>
 *  Max ops: 10
 *  Rating: 1
 */
int upperBits(int n) {
/*
  只需考虑0和非0的情况
  因高位填充1的数量是不可控的,所以要用>>算术右移来控制。
  当n=0时高位为0,当n=!0时高位为1,这样>>都可以满足,
  使用两次!!n即可满足。
  吧!!n放到最高位右移,右移此时为n-1次即可完成。因不能使用加法,只能采取+(-1),而0取反为-1。
  构造出(!!n<<31)>>(n+(~0))

*/
  return (!!n<<31)>>(n+(~0));
}

bitMatch

构建一个比特序列(int型),构成规则如下:如果x和y在某一个bit位置的值相同,则此序列的相应位置为1,否则该位置值为0。

/* 
 * bitMatch - Create mask indicating which bits in x match those in y
 *            using only ~ and & 
 *   Example: bitMatch(0x7, 0xE) = 0x6
 *   Legal ops: ~ & |
 *   Max ops: 14
 *   Rating: 1
 */
int bitMatch(int x, int y) {
/*
  根据题目要求和使用3种运算符,暴力写,加上一丢丢经验
  取
  x=0101, y=0110  相同位码为1100
  ~x=1010,~y=1001
  让他们碰一碰
  x&y=0100,~x&~y=1000
  写到这里就写出来了
  (x&y) | (~x&~y)。

  如果不行的话就去碰~x&y x&~y。
  
*/  
  return (x&y) | (~x&~y);
}

bitOr

计算按比特或(x | y),并将计算结果返回。

/* 
 * bitOr - x|y using only ~ and & 
 *   Example: bitOr(6, 5) = 7
 *   Legal ops: ~ &
 *   Max ops: 8
 *   Rating: 1
 */
int bitOr(int x, int y) {
/*
  根据题目要求和使用2种运算符,和上题一样暴力写,加上一丢丢经验
  取
  x=0101, y=0110  。x|y=0111
  ~x=1010,~y=1001
  让他们碰一碰
  ~x&~y=1000。(一般这种情况不会使用到x和y的原数据)
  写到这里就写出来了
  ~(~x&~y)
  
*/  
  return ~(~x&~y);
}

absVal

计算变量x的绝对值,并将其绝对值返回。

/* 
 * absVal - absolute value of x
 *   Example: absVal(-1) = 1.
 *   You may assume -TMax <= x <= TMax
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 10
 *   Rating: 4
 */
int absVal(int x) {
/*
  第一反应先对x取反+1,求x的负数即(~x+1),完成了对负数的绝对值,
  但此时正数变成了负数,不满足。
  找能不能使用x来使得正数变负数后用x经过一系列操作变成正数的操作Z,且负数变成正数经过操作Z还是保持不变。
  后来发现是不行了,即此输出是可能当输入的。

  负数和正数的区别在与最高位的1/0,可使用^1或^0,来得到负数的取反操作且正数保持不变。
  取反已完成,还剩下一个+1操作。此+1操作要使负数才+1而正数是+0。
  利用它们的区别,负数最高为1,正数最高为0.
  ~1+1=0+1=1,~0+1。
  我们可以使用溢出来完成。
  即(~(x>>31)+1)。当负数时~(0xffffffff)+1=1,当正数时~(0x00000000)+1=0(溢出)。

  如果可以用"-"op的话可以直接-(x>>31)

*/
  return (x^(x>>31))+(~(x>>31)+1);
}

logicalNeg

使用位操作符实现逻辑非(!x)操作,并将取逻辑非之后的结果返回。

/* 
 * 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) {
/*
  仔细观察,!0=1,!非0的数就是1。而我们不知道x具体的位数,而且不能使用循环判断。
  可以利用补码与原码来进行判断,x|(~x+1)。因为x|(~x)=11...11,不能区分0,所以使用补码x|(~x+1)。
  这样,
  如果是非零数,经过x|(~x+1),最高位一定是1
  如果是0,经过x|(~x+1),最高位是0
  利用溢出,((x|(~x+1))>>31)+1即完成。
 
 */
  return ((x|(~x+1))>>31)+1;
}

bitParity

如果x中包含奇数个0,则返回1;否则返回0。

/*
 * bitParity - returns 1 if x contains an odd number of 0's
 *   Examples: bitParity(5) = 0, bitParity(7) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 20
 *   Rating: 4
 */
int bitParity(int x) {
/*
  奇数个0和奇数个1是一样的意思。
  奇数个1返回1,否则返回0。
  用^。1^1^1返回1,1^0^1返回0,
  也就是有奇数个1^时返回1,偶数个1^时返回0。
  利用这一特性,
  把高16位和低16位^,然后在拿结果高8位和低8位^.....高1位和低1位^,最后得出最高位的一个数。
  利用特性,把最高位右移到最低位 >>31,两次!,即可得出结果
  
  :思路来源于百度,留下了没技术的泪水。
*/
  x=x^(x<<16);
  x=x^(x<<8);
  x=x^(x<<4);
  x=x^(x<<2);
  x=x^(x<<1);
  return !!(x>>31);
}

byteSwap

将x的第n字节和第m字节交换,0 <= n <= 3, 0 <= m <= 3,然后将交换后的值返回。

/* 
 * byteSwap - swaps the nth byte and the mth byte
 *  Examples: byteSwap(0x12345678, 1, 3) = 0x56341278
 *            byteSwap(0xDEADBEEF, 0, 2) = 0xDEEFBEAD
 *  You may assume that 0 <= n <= 3, 0 <= m <= 3
 *  Legal ops: ! ~ & ^ | + << >>
 *  Max ops: 25
 *  Rating: 2
 */
int byteSwap(int x, int n, int m) {
/*
    先把n、m处的字节提取出来成a、b。n<<3=n*8,是因为1字节=8位,要定位到n字节就*8。&0xff只取低8位
    在把a、b扩位到它要放入的位成am、bn
    在把x处的n、m字节重置为0,利用y+(~y+1)(补码)=0的性质,成bm、an,bm&an即x处的n、m字节重置为0
    在把它们结合起来成bn|am|(an&bm),即完成。

    :可把n<<3,m<<3用变量存储。但是不利于阅读。
    用了好多个op...。刚开始刚好用了25个op,好巧。

    2.0:
    写下面的replaceByte(int x, int n, int c)时,
    发现可以使用x&~(0xff<<(n<<3))来使n字节变成0。
    于是
    int bm = x+(~(b<<(m<<3))+1)
    int an = x+(~(a<<(n<<3))+1)
    可以替换成int mask = x&~((0xff<<(n<<3)|0xff<<(m<<3)))节省了op
*/

    int a = (x>>(n<<3))&0xff;   
    int b = (x>>(m<<3))&0xff;   
    int am = a<<(m<<3);
    int bn = b<<(n<<3);

    int mask = x&~((0xff<<(n<<3)|0xff<<(m<<3)));

    //int bm = x+(~(b<<(m<<3))+1);
    //int an = x+(~(a<<(n<<3))+1);

    return bn|am|mask;
}

getByte

提取x的第n个字节。0 <= n <= 3 (0代表最最低为字节,3代表最高位字节),并将其返回。

/* 
 * getByte - Extract byte n from word x
 *   Bytes numbered from 0 (least significant) to 3 (most significant)
 *   Examples: getByte(0x12345678,1) = 0x56
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 6
 *   Rating: 2
 */
int getByte(int x, int n) {
/*
  在byteSwap(int x,int n,int m)函数中已经实现了此操作。
  n<<3=n*8,是因为1字节=8位,要定位到n字节就*8。
  &0xff只取低8位
*/
  return (x>>(n<<3))&0xff;
}

isGreater

如果x > y,则返回1,否则返回0。

/* 
 * isGreater - if x > y  then return 1, else return 0 
 *   Example: isGreater(4,5) = 0, isGreater(5,4) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 24
 *   Rating: 3
 */
int isGreater(int x, int y) {
/*
  这题好难,回过头来看草稿。写出来只能满足大部分数,
  当遇到0x7fffffff、0x80000000、0x80000001数是总是不符合要求。

  上百度上找到了答案改了一下

  1.正数比负数大
  2.负数比正数小
  3.两数相减为正数时返回1
  4.相等返回0

  (!a&b)|!c:
  x是正数,y是负数,返回1。x是正数,y是正数,则看后面的相减是否为正数(!c),为正返回1。
  x是负数,y是正数,返回0。x是负数,y是负数,则看后面的相减是否为正数(!c),为正返回1。
  写(!a&b)|!c还不够,
  还要防止x-y的溢出,使负数变成正数0x80000000-0x7fffffff=0x80000000+0x80000001=0x00000001,
  产生错误的返回结果。
  (!a) | b):只要y为负或x为正即可。
  判断相等返回0:!!(x ^ y)
  合并即return (( (!a)&b) | !c) & ( (!a) | b) & !!(x ^ y);
*/
  int a = (x>>31),b=(y>>31);
  int sub = x + (~y+1);
  int c = (sub>>31);
  return (( (!a)&b) | !c) & ( (!a) | b) & !!(x ^ y);
}

isNegative

如果x < 0,返回1;否则返回0。

/* 
 * isNegative - return 1 if x < 0, return 0 otherwise 
 *   Example: isNegative(-1) = 1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 6
 *   Rating: 2
 */
int isNegative(int x) {
/*
  依题意,负数返回1。其他返回0
  负数就是最高位为1。
  让x>>31最高位变成最低位再^0xf>>31如果等于0说明x是负数,!!取0
  即(x>>31^0xf>>31),如果不等于0说明x是非负,!!取1
  即!!((x>>31)^0xf>>31)

  想了想,^0xf>>31有点复杂,可以直接~(x>>31),
  如果x是负数(最高位为1)此时就等于0
  如果x是正数和0(最高位为0)此时就等于1
  在取!即可
  即!~(x>>31)

*/
  return !~(x>>31);
}

isPower2

如果x是2的整数次幂,则返回1;否则返回0。

/*
 * isPower2 - returns 1 if x is a power of 2, and 0 otherwise
 *   Examples: isPower2(5) = 0, isPower2(8) = 1, isPower2(0) = 0
 *   Note that no negative number is a power of 2.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 20
 *   Rating: 4
 */
int isPower2(int x) {
/*
  每个数在二进制中都是唯一的。
  也就是2的幂,在二进制中只有一位是1其他全是0才有可能是2的幂(除了第一位是1不是2的幂)
  即可以用x&(x-1)来判断,如果只有一个1返回0,加个!,
  !(x&(x+(~0)))。
  还要判断是不是负数,是负数就返回0(!!~(x>>31)
  还要判断是不是0,是0也要返回0!!x
  合并起来就是
  (!!~(x>>31) & !(x & (x + (~0)))) & !!x
*/
  return (!!~(x>>31) & !(x & (x + (~0)))) & !!x;
}

addOK

如果x+y没有溢出,则返回1;否则返回0。

/* 
 * addOK - Determine if can compute x+y without overflow
 *   Example: addOK(0x80000000,0x80000000) = 0,
 *            addOK(0x80000000,0x70000000) = 1, 
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 20
 *   Rating: 3
 */
int addOK(int x, int y) {
/*
  依课本P65页给出的条件:
  令s=x+y
  当且仅当x>0,y>0,但s<=0时,计算s发生了正溢出
  当且仅当x<0,y<0,但s>=0时,计算s发生了负溢出

  参考练习题2.30写出
  int sum=x+y;
  int nag_over = x>>31 & y>>31 & ((!(sum>>31))|(!sum));
  int pos_over = !(x>>31) & !(y>>31) & sum>>31;  
  return !nag_over & !pos_over;

  改进:
  发现条件可以概括为:x和y符号位相同,且x和sum符号位不同时,发生了溢出。

*/
  int sum=x+y;

  return !((!(x>>31 ^ y>>31)) & (x>>31 ^ sum>>31));
}

subtractionOK

如果x-y没有溢出,则返回1;否则返回0。

/* 
 * subtractionOK - Determine if can compute x-y without overflow
 *   Example: subtractionOK(0x80000000,0x80000000) = 1,
 *            subtractionOK(0x80000000,0x70000000) = 0, 
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 20
 *   Rating: 3
 */
int subtractionOK(int x, int y) {
/*
  参考addOK函数
  int sum = x+(~y+1)  //x-y
  条件为:x和y符号位不同,且x和sum符号位不同时,发生了溢出。
*/  
  int sum=x+(~y+1);

  return !((x>>31 ^ y>>31) & (x>>31 ^ sum>>31));
}

oddBits

返回一个32bit数,这数的所有第奇数个bit位置的值为1。

/* 
 * oddBits - return word with all odd-numbered bits set to 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 8
 *   Rating: 2
 */
int oddBits(void) {
  //构造掩码1010(0xa)即可
  return (0xaa) + (0xaa<<8) + (0xaa<<16) + (0xaa<<24);
}

replaceByte

将x的第n个字节用 c 进行替换,0 <= n <= 3, 0 <= c <= 255 并将替换后的结果返回。

/* 
 * replaceByte(x,n,c) - Replace byte n in x with c
 *   Bytes numbered from 0 (LSB) to 3 (MSB)
 *   Examples: replaceByte(0x12345678,1,0xab) = 0x1234ab78
 *   You can assume 0 <= n <= 3 and 0 <= c <= 255
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 10
 *   Rating: 3
 */
int replaceByte(int x, int n, int c) {
/*
  把c移位到它要放入的字节。
  创建源码使x在c字节处为0。
  两者取|
*/
  int a = c<<(n<<3);
  int mask = x&~(0xff<<(n<<3));
  return a|mask;
}

rotateLeft

将x向左循环移位n个bit。循环移位是指左边移除去的比特自动填充到右边空出的位置上。0 <= n <= 31,并将循环移位后的值返回。

/* 
 * rotateLeft - Rotate x to the left by n
 *   Can assume that 0 <= n <= 31
 *   Examples: rotateLeft(0x87654321,4) = 0x76543218
 *   Legal ops: ~ & ^ | + << >> !
 *   Max ops: 25
 *   Rating: 3 
 */
int rotateLeft(int x, int n) {
/*
  创建一个掩码把n高位获取出来 (x & ((1<<n)-1))是取低n位,
  利用取反+左移改成取高位((x & ~((1<<(32-n))-1))>>(32-n))

  最高位为1时,右取高位会有点小问题,右移产生了1。再创建一个掩码,来使最高位为1时右移所产生的1变成0
  创建一个掩码,低n位为1,使用&就可以把右移所产生的1变成0
  掩码为:~(((1<<(32-n))-1)<<n)
  即:((x & ~((1<<(32-n))-1))>>(32-n)) & ~(((1<<(32-n))-1)<<n),获取了高位

  获取32-n位,在左移n位,空出位置来放n高位
  即:(x& ((1<<(32-n))-1))<<n)

  在把 获取到的高位 | (x& ((1<<(32-n))-1))<<n) 即可
  即:((x& ((1<<(32-n))-1))<<n) | (((x & ~((1<<(32-n))-1))>>(32-n)) & ~(((1<<(32-n))-1)<<n))
----------------------

  :有一个有趣的。创建一个掩码,低n位为1
  可以用这个操作来进行代替。
  掩码:(0 | ((1<<n)-1))。即构建一个低n位为1的数,
  即:((x & ~((1<<(32-n))-1))>>(32-n)) & (0 | ((1<<n)-1)),获取了n高位
  正常来说是没问题的,但是在当n=0时,程序就出现了错误(0 | ((1<<0)-1))=0,&0肯定为0

  所以还是用上面的操作。
*/
  int nag_1 = ~0;
  int sub_n = 32+(~n+1);
  int get_exc_hight_n_bit=(1<<sub_n)+nag_1;
  return ((x& (get_exc_hight_n_bit))<<n) | 
(((x & ~(get_exc_hight_n_bit))>>(sub_n)) & ~((get_exc_hight_n_bit)<<n));
}

floatAbsVal

通过bit级操作返回一个float型浮点数的绝对值。如果输入参数为NaN,则直接返回输入参数的原值。

/* 
 * floatAbsVal - Return bit-level equivalent of absolute value of 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 representations of
 *   single-precision floating point values.
 *   When argument is NaN, return argument..
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
 *   Max ops: 10
 *   Rating: 2
 */
unsigned floatAbsVal(unsigned uf) {
/*
  根据课本P78给出浮点表示格式
  最高位为符号位s,负数(s=1)和正数(s=0)
  取绝对值只要把符号位置为0,x=uf&0x7fffffff   (没有大小限制了真好)
  NaN的表示为s11111111(经过上面的符号位改变,此时s=0) 其他位不为0
  只要x比011111111(0x7f8)大说明x为NaN
*/
  int x=uf&0x7fffffff;
  if(x>0x7f800000)
    return uf;
  else
    return x;
}

floatIsEqual

判断两个浮点数是否相等,如果相等则返回1,否则返回0。
如果输入参数中含有NaN,则返回0。
注:+0和-0被当作相等的情况对待。

/* 
 * floatIsEqual - Compute f == g for floating point arguments f and g.
 *   Both the arguments are passed as unsigned int's, but
 *   they are to be interpreted as the bit-level representations of
 *   single-precision floating point values.
 *   If either argument is NaN, return 0.
 *   +0 and -0 are considered equal.
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
 *   Max ops: 25
 *   Rating: 2
 */
int floatIsEqual(unsigned uf, unsigned ug) {
/*
  先来一手uf==ug试试水。
  哦豁果然不行,挂在0和(0x80000000)。
  那就判断uf和ug是不是0和0x80000000。
  还要判断是不是NaN。判断符号位对应的NaN
  上面所有都不是的话,那就直接到uf==ug就好了
*/

    int min = 0x80000000;

    if((uf==0 && ug==min) || (uf==min && ug==0) || (uf==min && ug==min))
      return 1;

    if(uf&0x80000000){
      if(uf>0xff800000){
        return 0;
      }
    }else if(uf>0x7f800000){
      return 0;
    }
    
    if(ug&0x80000000){
      if(ug>0xff800000){
        return 0;
      }
    }else if(ug>0x7f800000){
      return 0;
    }
    
    return uf == ug;
}

全部题

/* 
 * CS:APP Data Lab 
 * 
 * <Please put your name and userid here>
 * 
 * bits.c - Source file with your solutions to the Lab.
 *          This is the file you will hand in to your instructor.
 *
 * WARNING: Do not include the <stdio.h> header; it confuses the dlc
 * compiler. You can still use printf for debugging without including
 * <stdio.h>, although you might get a compiler warning. In general,
 * it's not good practice to ignore compiler warnings, but in this
 * case it's OK.  
 */

#if 0
/*
 * Instructions to Students:
 *
 * STEP 1: Read the following instructions carefully.
 */

You will provide your solution to the Data Lab by
editing the collection of functions in this source file.

INTEGER CODING RULES:
 
  Replace the "return" statement in each function with one
  or more lines of C code that implements the function. Your code 
  must conform to the following style:
 
  int Funct(arg1, arg2, ...) {
      /* brief description of how your implementation works */
      int var1 = Expr1;
      ...
      int varM = ExprM;

      varJ = ExprJ;
      ...
      varN = ExprN;
      return ExprR;
  }

  Each "Expr" is an expression using ONLY the following:
  1. Integer constants 0 through 255 (0xFF), inclusive. You are
      not allowed to use big constants such as 0xffffffff.
  2. Function arguments and local variables (no global variables).
  3. Unary integer operations ! ~
  4. Binary integer operations & ^ | + << >>
    
  Some of the problems restrict the set of allowed operators even further.
  Each "Expr" may consist of multiple operators. You are not restricted to
  one operator per line.

  You are expressly forbidden to:
  1. Use any control constructs such as if, do, while, for, switch, etc.
  2. Define or use any macros.
  3. Define any additional functions in this file.
  4. Call any functions.
  5. Use any other operations, such as &&, ||, -, or ?:
  6. Use any form of casting.
  7. Use any data type other than int.  This implies that you
     cannot use arrays, structs, or unions.

 
  You may assume that your machine:
  1. Uses 2s complement, 32-bit representations of integers.
  2. Performs right shifts arithmetically.
  3. Has unpredictable behavior when shifting if the shift amount
     is less than 0 or greater than 31.


EXAMPLES OF ACCEPTABLE CODING STYLE:
  /*
   * pow2plus1 - returns 2^x + 1, where 0 <= x <= 31
   */
  int pow2plus1(int x) {
     /* exploit ability of shifts to compute powers of 2 */
     return (1 << x) + 1;
  }

  /*
   * pow2plus4 - returns 2^x + 4, where 0 <= x <= 31
   */
  int pow2plus4(int x) {
     /* exploit ability of shifts to compute powers of 2 */
     int result = (1 << x);
     result += 4;
     return result;
  }

FLOATING POINT CODING RULES

For the problems that require you to implement floating-point operations,
the coding rules are less strict.  You are allowed to use looping and
conditional control.  You are allowed to use both ints and unsigneds.
You can use arbitrary integer and unsigned constants. You can use any arithmetic,
logical, or comparison operations on int or unsigned data.

You are expressly forbidden to:
  1. Define or use any macros.
  2. Define any additional functions in this file.
  3. Call any functions.
  4. Use any form of casting.
  5. Use any data type other than int or unsigned.  This means that you
     cannot use arrays, structs, or unions.
  6. Use any floating point data types, operations, or constants.


NOTES:
  1. Use the dlc (data lab checker) compiler (described in the handout) to 
     check the legality of your solutions.
  2. Each function has a maximum number of operations (integer, logical,
     or comparison) that you are allowed to use for your implementation
     of the function.  The max operator count is checked by dlc.
     Note that assignment ('=') is not counted; you may use as many of
     these as you want without penalty.
  3. Use the btest test harness to check your functions for correctness.
  4. Use the BDD checker to formally verify your functions
  5. The maximum number of ops for each function is given in the
     header comment for each function. If there are any inconsistencies 
     between the maximum ops in the writeup and in this file, consider
     this file the authoritative source.

/*
 * STEP 2: Modify the following functions according the coding rules.
 * 
 *   IMPORTANT. TO AVOID GRADING SURPRISES:
 *   1. Use the dlc compiler to check that your solutions conform
 *      to the coding rules.
 *   2. Use the BDD checker to formally verify that your solutions produce 
 *      the correct answers.
 */


#endif
/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, see
   <http://www.gnu.org/licenses/>.  */
/* This header is separate from features.h so that the compiler can
   include it implicitly at the start of every compilation.  It must
   not itself include <features.h> or any other header that includes
   <features.h> because the implicit include comes before any feature
   test macros that may be defined in a source file before it first
   explicitly includes a system header.  GCC knows the name of this
   header in order to preinclude it.  */
/* glibc's intent is to support the IEC 559 math functionality, real
   and complex.  If the GCC (4.9 and later) predefined macros
   specifying compiler intent are available, use them to determine
   whether the overall intent is to support these features; otherwise,
   presume an older compiler has intent to support these features and
   define these macros by default.  */
/* wchar_t uses Unicode 10.0.0.  Version 10.0 of the Unicode Standard is
   synchronized with ISO/IEC 10646:2017, fifth edition, plus
   the following additions from Amendment 1 to the fifth edition:
   - 56 emoji characters
   - 285 hentaigana
   - 3 additional Zanabazar Square characters */
/* We do not support C11 <threads.h>.  */
/*
 * isZero - returns 1 if x == 0, and 0 otherwise 
 *   Examples: isZero(5) = 0, isZero(0) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 2
 *   Rating: 1
 */
int isZero(int x) {
/*
  没啥好说的。x^0。
  x=0时,x^0=0。
  x!=0时,x^0=1。
  在取非(!)
*/
  return !(x^0);
}
/* 
 * negate - return -x 
 *   Example: negate(1) = -1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 5
 *   Rating: 2
 */
int negate(int x) {
/*
  没啥好说的。
  补码与原码取反加1
*/
  return ~x + 1;
}
/* 
 * specialBits - return bit pattern 0xffca3fff
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 3
 *   Rating: 1
 */
int specialBits(void) {
/*
  因int取值为0~255,
  刚开始的思路是创建两个变量,使用位移构造出ca3。
  0xff...fff肯定是要取反获得的了,所以刚开始就构造0xca3的反码0x35c,
  在位移使(0x0035c000),取反即完成。
  所以可得(~((0x35<<16)|(0xc0<<8))=0xffca3fff。
  发现使用了4op,不合题意。

  分析有没有可以优化的,
  取反~占1op,构造0x35c"要对0x35使用位移1op,合并成0x35,0xc也要1op,位移到正确的位置1op。
  想到能不能使用加法来构造0x35c这样位移+合并的2op就变成加法的1op。
  发现int+int到不了0x35c,不过这是一个很好的思路,用其他的办法来构造0x35c
  0x35c二进制为0011 0101 1100,发现低2位和高2位都是0,可以吧0x35c>>2=1101 0111=0xD7
  所以0x35c可以表示为0xD7<<2,很好,在把0x35c位移到合适的位置,即
  0xD7<<2<<12=0xD7<<14
  取反即~(0XD7<<14)返回0xffca3fff

*/
  //0xD7<<2<<12, D7<<2 = 35c,
  return ~(0XD7<<14);
}
/* 
 * upperBits - pads n upper bits with 1's
 *  You may assume 0 <= n <= 32
 *  Example: upperBits(4) = 0xF0000000
 *  Legal ops: ! ~ & ^ | + << >>
 *  Max ops: 10
 *  Rating: 1
 */
int upperBits(int n) {
/*
  只需考虑0和非0的情况
  因高位填充1的数量是不可控的,所以要用>>算术右移来控制。
  当n=0时高位为0,当n=!0时高位为1,这样>>都可以满足,
  使用两次!!n即可满足。
  吧!!n放到最高位右移,右移此时为n-1次即可完成。因不能使用加法,只能采取+(-1),而0取反为-1。
  构造出(!!n<<31)>>(n+(~0))

*/
  return (!!n<<31)>>(n+(~0));
}
/* 
 * bitMatch - Create mask indicating which bits in x match those in y
 *            using only ~ and & 
 *   Example: bitMatch(0x7, 0xE) = 0x6
 *   Legal ops: ~ & |
 *   Max ops: 14
 *   Rating: 1
 */
int bitMatch(int x, int y) {
/*
  根据题目要求和使用3种运算符,暴力写,加上一丢丢经验
  取
  x=0101, y=0110  相同位码为1100
  ~x=1010,~y=1001
  让他们碰一碰
  x&y=0100,~x&~y=1000
  写到这里就写出来了
  (x&y) | (~x&~y)。

  如果不行的话就去碰~x&y x&~y。
  
*/  
  return (x&y) | (~x&~y);
}
/* 
 * bitOr - x|y using only ~ and & 
 *   Example: bitOr(6, 5) = 7
 *   Legal ops: ~ &
 *   Max ops: 8
 *   Rating: 1
 */
int bitOr(int x, int y) {
/*
  根据题目要求和使用2种运算符,和上题一样暴力写,加上一丢丢经验
  取
  x=0101, y=0110  。x|y=0111
  ~x=1010,~y=1001
  让他们碰一碰
  ~x&~y=1000。(一般这种情况不会使用到x和y的原数据)
  写到这里就写出来了
  ~(~x&~y)
  
*/  
  return ~(~x&~y);
}
/* 
 * absVal - absolute value of x
 *   Example: absVal(-1) = 1.
 *   You may assume -TMax <= x <= TMax
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 10
 *   Rating: 4
 */
int absVal(int x) {
/*
  第一反应先对x取反+1,求x的负数即(~x+1),完成了对负数的绝对值,
  但此时正数变成了负数,不满足。
  找能不能使用x来使得正数变负数后用x经过一系列操作变成正数的操作Z,且负数变成正数经过操作Z还是保持不变。
  后来发现是不行了,即此输出是可能当输入的。

  负数和正数的区别在与最高位的1/0,可使用^1或^0,来得到负数的取反操作且正数保持不变。
  取反已完成,还剩下一个+1操作。此+1操作要使负数才+1而正数是+0。
  利用它们的区别,负数最高为1,正数最高为0.
  ~1+1=0+1=1,~0+1。
  我们可以使用溢出来完成。
  即(~(x>>31)+1)。当负数时~(0xffffffff)+1=1,当正数时~(0x00000000)+1=0(溢出)。

  如果可以用"-"op的话可以直接-(x>>31)

*/
  return (x^(x>>31))+(~(x>>31)+1);
}
/* 
 * 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) {
/*
  仔细观察,!0=1,!非0的数就是1。而我们不知道x具体的位数,而且不能使用循环判断。
  可以利用补码与原码来进行判断,x|(~x+1)。因为x|(~x)=11...11,不能区分0,所以使用补码x|(~x+1)
  这样,
  如果是非零数,经过x|(~x+1),最高位一定是1
  如果是0,经过x|(~x+1),最高位是0
  利用溢出,((x|(~x+1))>>31)+1即完成。
 
 */
  return ((x|(~x+1))>>31)+1;
}
/*
 * bitParity - returns 1 if x contains an odd number of 0's
 *   Examples: bitParity(5) = 0, bitParity(7) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 20
 *   Rating: 4
 */
int bitParity(int x) {
/*
  奇数个0和奇数个1是一样的意思。
  奇数个1返回1,否则返回0。
  用^。1^1^1返回1,1^0^1返回0,
  也就是有奇数个1^时返回1,偶数个1^时返回0。
  利用这一特性,
  把高16位和低16位^,然后在拿结果高8位和低8位^.....高1位和低1位^,最后得出最高位的一个数。
  利用特性,把最高位右移到最低位 >>31,两次!,即可得出结果
  
  :思路来源于百度,留下了没技术的泪水。
*/
  x=x^(x<<16);
  x=x^(x<<8);
  x=x^(x<<4);
  x=x^(x<<2);
  x=x^(x<<1);
  return !!(x>>31);
}
/* 
 * byteSwap - swaps the nth byte and the mth byte
 *  Examples: byteSwap(0x12345678, 1, 3) = 0x56341278
 *            byteSwap(0xDEADBEEF, 0, 2) = 0xDEEFBEAD
 *  You may assume that 0 <= n <= 3, 0 <= m <= 3
 *  Legal ops: ! ~ & ^ | + << >>
 *  Max ops: 25
 *  Rating: 2
 */
int byteSwap(int x, int n, int m) {
/*
    先把n、m处的字节提取出来成a、b。n<<3=n*8,是因为1字节=8位,要定位到n字节就*8。&0xff只取低8位
    在把a、b扩位到它要放入的位成am、bn
    在把x处的n、m字节重置为0,利用y+(~y+1)(补码)=0的性质,成bm、an,bm&an即x处的n、m字节重置为0
    在把它们结合起来成bn|am|(an&bm),即完成。

    :可把n<<3,m<<3用变量存储。但是不利于阅读。
    用了好多个op...。刚开始刚好用了25个op,好巧。

    2.0:
    写下面的replaceByte(int x, int n, int c)时,
    发现可以使用x&~(0xff<<(n<<3))来使n字节变成0。
    于是
    int bm = x+(~(b<<(m<<3))+1)
    int an = x+(~(a<<(n<<3))+1)
    可以替换成int mask = x&~((0xff<<(n<<3)|0xff<<(m<<3)))节省了op
*/

    int a = (x>>(n<<3))&0xff;   
    int b = (x>>(m<<3))&0xff;   
    int am = a<<(m<<3);
    int bn = b<<(n<<3);

    int mask = x&~((0xff<<(n<<3)|0xff<<(m<<3)));

    //int bm = x+(~(b<<(m<<3))+1);
    //int an = x+(~(a<<(n<<3))+1);

    return bn|am|mask;
}
/* 
 * getByte - Extract byte n from word x
 *   Bytes numbered from 0 (least significant) to 3 (most significant)
 *   Examples: getByte(0x12345678,1) = 0x56
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 6
 *   Rating: 2
 */
int getByte(int x, int n) {
/*
  在byteSwap(int x,int n,int m)函数中已经实现了此操作。
  n<<3=n*8,是因为1字节=8位,要定位到n字节就*8。
  &0xff只取低8位
*/
  return (x>>(n<<3))&0xff;
}
/* 
 * isGreater - if x > y  then return 1, else return 0 
 *   Example: isGreater(4,5) = 0, isGreater(5,4) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 24
 *   Rating: 3
 */
int isGreater(int x, int y) {
/*
  这题好难,回过头来看草稿。写出来只能满足大部分数,
  当遇到0x7fffffff、0x80000000、0x80000001数是总是不符合要求。

  上百度上找到了答案改了一下

  1.正数比负数大
  2.负数比正数小
  3.两数相减为正数时返回1
  4.相等返回0

  (!a&b)|!c:
  x是正数,y是负数,返回1。x是正数,y是正数,则看后面的相减是否为正数(!c),为正返回1。
  x是负数,y是正数,返回0。x是负数,y是负数,则看后面的相减是否为正数(!c),为正返回1。
  写(!a&b)|!c还不够,
  还要防止x-y的溢出,使负数变成正数0x80000000-0x7fffffff=0x80000000+0x80000001=0x00000001,
  产生错误的返回结果。
  (!a) | b):只要y为负或x为正即可。
  判断相等返回0:!!(x ^ y)
  合并即return (( (!a)&b) | !c) & ( (!a) | b) & !!(x ^ y);
*/
  int a = (x>>31),b=(y>>31);
  int sub = x + (~y+1);
  int c = (sub>>31);
  return (( (!a)&b) | !c) & ( (!a) | b) & !!(x ^ y);
}
/* 
 * isNegative - return 1 if x < 0, return 0 otherwise 
 *   Example: isNegative(-1) = 1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 6
 *   Rating: 2
 */
int isNegative(int x) {
/*
  依题意,负数返回1。其他返回0
  负数就是最高位为1。
  让x>>31最高位变成最低位再^0xf>>31如果等于0说明x是负数,!!取0
  即(x>>31^0xf>>31),如果不等于0说明x是非负,!!取1
  即!!((x>>31)^0xf>>31)

  想了想,^0xf>>31有点复杂,可以直接~(x>>31),
  如果x是负数(最高位为1)此时就等于0
  如果x是正数和0(最高位为0)此时就等于1
  在取!即可
  即!~(x>>31)

*/
  return !~(x>>31);
}
/*
 * isPower2 - returns 1 if x is a power of 2, and 0 otherwise
 *   Examples: isPower2(5) = 0, isPower2(8) = 1, isPower2(0) = 0
 *   Note that no negative number is a power of 2.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 20
 *   Rating: 4
 */
int isPower2(int x) {
/*
  每个数在二进制中都是唯一的。
  也就是2的幂,在二进制中只有一位是1其他全是0才有可能是2的幂(除了第一位是1不是2的幂)
  即可以用x&(x-1)来判断,如果只有一个1返回0,加个!,
  !(x&(x+(~0)))。
  还要判断是不是负数,是负数就返回0(!!~(x>>31)
  还要判断是不是0,是0也要返回0!!x
  合并起来就是
  (!!~(x>>31) & !(x & (x + (~0)))) & !!x
*/
  return (!!~(x>>31) & !(x & (x + (~0)))) & !!x;
}
/* 
 * addOK - Determine if can compute x+y without overflow
 *   Example: addOK(0x80000000,0x80000000) = 0,
 *            addOK(0x80000000,0x70000000) = 1, 
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 20
 *   Rating: 3
 */
int addOK(int x, int y) {
/*
  依课本P65页给出的条件:
  令s=x+y
  当且仅当x>0,y>0,但s<=0时,计算s发生了正溢出
  当且仅当x<0,y<0,但s>=0时,计算s发生了负溢出

  参考练习题2.30写出
  int sum=x+y;
  int nag_over = x>>31 & y>>31 & ((!(sum>>31))|(!sum));
  int pos_over = !(x>>31) & !(y>>31) & sum>>31;  
  return !nag_over & !pos_over;

  改进:
  发现条件可以概括为:x和y符号位相同,且x和sum符号位不同时,发生了溢出。

*/
  int sum=x+y;

  return !((!(x>>31 ^ y>>31)) & (x>>31 ^ sum>>31));
}
/* 
 * subtractionOK - Determine if can compute x-y without overflow
 *   Example: subtractionOK(0x80000000,0x80000000) = 1,
 *            subtractionOK(0x80000000,0x70000000) = 0, 
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 20
 *   Rating: 3
 */
int subtractionOK(int x, int y) {
/*
  参考addOK函数
  int sum = x+(~y+1)  //x-y
  条件为:x和y符号位不同,且x和sum符号位不同时,发生了溢出。
*/  
  int sum=x+(~y+1);

  return !((x>>31 ^ y>>31) & (x>>31 ^ sum>>31));
}
/* 
 * oddBits - return word with all odd-numbered bits set to 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 8
 *   Rating: 2
 */
int oddBits(void) {
  //构造掩码1010(0xa)即可
  return (0xaa) + (0xaa<<8) + (0xaa<<16) + (0xaa<<24);
}
/* 
 * replaceByte(x,n,c) - Replace byte n in x with c
 *   Bytes numbered from 0 (LSB) to 3 (MSB)
 *   Examples: replaceByte(0x12345678,1,0xab) = 0x1234ab78
 *   You can assume 0 <= n <= 3 and 0 <= c <= 255
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 10
 *   Rating: 3
 */
int replaceByte(int x, int n, int c) {
/*
  把c移位到它要放入的字节。
  创建源码使x在c字节处为0。
  两者取|
*/
  int a = c<<(n<<3);
  int mask = x&~(0xff<<(n<<3));
  return a|mask;
}
/* 
 * rotateLeft - Rotate x to the left by n
 *   Can assume that 0 <= n <= 31
 *   Examples: rotateLeft(0x87654321,4) = 0x76543218
 *   Legal ops: ~ & ^ | + << >> !
 *   Max ops: 25
 *   Rating: 3 
 */
int rotateLeft(int x, int n) {
/*
  创建一个掩码把n高位获取出来 (x & ((1<<n)-1))是取低n位,
  利用取反+左移改成取高位((x & ~((1<<(32-n))-1))>>(32-n))

  最高位为1时,右取高位会有点小问题,右移产生了1。再创建一个掩码,来使最高位为1时右移所产生的1变成0
  创建一个掩码,低n位为1,使用&就可以把右移所产生的1变成0
  掩码为:~(((1<<(32-n))-1)<<n)
  即:((x & ~((1<<(32-n))-1))>>(32-n)) & ~(((1<<(32-n))-1)<<n),获取了高位

  获取32-n位,在左移n位,空出位置来放n高位
  即:(x& ((1<<(32-n))-1))<<n)

  在把 获取到的高位 | (x& ((1<<(32-n))-1))<<n) 即可
  即:((x& ((1<<(32-n))-1))<<n) | (((x & ~((1<<(32-n))-1))>>(32-n)) & ~(((1<<(32-n))-1)<<n))
----------------------

  :有一个有趣的。创建一个掩码,低n位为1
  可以用这个操作来进行代替。
  掩码:(0 | ((1<<n)-1))。即构建一个低n位为1的数,
  即:((x & ~((1<<(32-n))-1))>>(32-n)) & (0 | ((1<<n)-1)),获取了n高位
  正常来说是没问题的,但是在当n=0时,程序就出现了错误(0 | ((1<<0)-1))=0,&0肯定为0

  所以还是用上面的操作。
*/
  int nag_1 = ~0;
  int sub_n = 32+(~n+1);
  int get_exc_hight_n_bit=(1<<sub_n)+nag_1;
  return ((x& (get_exc_hight_n_bit))<<n) | 
(((x & ~(get_exc_hight_n_bit))>>(sub_n)) & ~((get_exc_hight_n_bit)<<n));
}
/* 
 * floatAbsVal - Return bit-level equivalent of absolute value of 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 representations of
 *   single-precision floating point values.
 *   When argument is NaN, return argument..
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
 *   Max ops: 10
 *   Rating: 2
 */
unsigned floatAbsVal(unsigned uf) {
/*
  根据课本P78给出浮点表示格式
  最高位为符号位s,负数(s=1)和正数(s=0)
  取绝对值只要把符号位置为0,x=uf&0x7fffffff   (没有大小限制了真好)
  NaN的表示为s11111111(经过上面的符号位改变,此时s=0) 其他位不为0
  只要x比011111111(0x7f8)大说明x为NaN
*/
  int x=uf&0x7fffffff;
  if(x>0x7f800000)
    return uf;
  else
    return x;
}
/* 
 * floatIsEqual - Compute f == g for floating point arguments f and g.
 *   Both the arguments are passed as unsigned int's, but
 *   they are to be interpreted as the bit-level representations of
 *   single-precision floating point values.
 *   If either argument is NaN, return 0.
 *   +0 and -0 are considered equal.
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
 *   Max ops: 25
 *   Rating: 2
 */
int floatIsEqual(unsigned uf, unsigned ug) {
/*
  先来一手uf==ug试试水。
  哦豁果然不行,挂在0和(0x80000000)。
  那就判断uf和ug是不是0和0x80000000。
  还要判断是不是NaN。判断符号位对应的NaN
  上面所有都不是的话,那就直接到uf==ug就好了
*/

    int min = 0x80000000;

    if((uf==0 && ug==min) || (uf==min && ug==0) || (uf==min && ug==min))
      return 1;

    if(uf&0x80000000){
      if(uf>0xff800000){
        return 0;
      }
    }else if(uf>0x7f800000){
      return 0;
    }
    
    if(ug&0x80000000){
      if(ug>0xff800000){
        return 0;
      }
    }else if(ug>0x7f800000){
      return 0;
    }
    
    return uf == ug;
}

运行

这是我们学校的命令,非官方的。
./dlc bits.c:直接检测是否有错误
./dlc -e bits.c:观察操作符数
make:编译
./btest:测分
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐