CSAPP---datalab

262 阅读2分钟

1.bitXor-- 要求只用取反和与运算来表示异或运算

首先我们看真值表

image.png x^y=~xy+~yx X^y=(~x&y)+(~y&x) 但是题目要求只能用取反和与运算,所以这种方式是不行的 我们来看狄摩根定律

image.png

image.png

2.求整型数补码的最小值

对于int类型的数据最小值就是1000000000000000 用十六进制也就是0x8000000,但是要求这个数不能超过8个比特位。所以我们想到了算术右移 也就是 0x1<<31

3.判断x是不是补码表示的最大值

image.png

4.判断x所有的奇数位是不是等于1

首先先找一个数它的奇数位全都是1,让x按位&,这样生成一个偶数位全为0的数,再与奇数位的数进行^,生成的数如果全为1,那么就是要找的数,否则就不是

5.返回-x

一个有用的结论是-x=~x+1. 很简单x+~x=1111 1111 1111 1111 1111 1111 1111 1111=-1 x+~x+1=0,答案就很明了了

6.返回1,如果x在0x30和0x39之间

利用上一题的结论 x-0x30 就是x+(~0x30)+1, 所以利用这个结论表示出两个数的差,差如果大于0的话,意味着最高位等于0,再左移31位取反,就是全为1,然后需要两个差都为1,才能满足要求

7.实现三目运算符,如果x不等于0就返回y,如果x等于0就返回z

首先用!!x表示是否x为0,如果为0,就是0,如果不为0就是1 再用~(!!x)表示全为1的数,和全为0的数, int conditional = !!x;//如果x为0,结果就是0,如果x不为0,结果就是1 int flag = ~conditional + 1; int ret_y = flag & y; int ret_z = ~flag * z; return ret_y & ret_z;

8.使用除了逻辑非之外的操作符来实现逻辑非

对于这个函数来说输入0返回1,其他都返回0,我们借助-x的表述,对于所有不为0的数来说,-x的第一位或者x的第一位肯定有一个为1,那么或运算的结果第一位肯定是1,然后左移31为那就是每一位都是1了,要是为0,那就相反了。所以答案就显而易见了。

9.当使用补码来表示一个数的时候,最少需要几个比特位

比如12要使用五个比特位 0000 0000 0000 0000 0000 0000 1100 直观的解法就是从左往右数第一个1 这一题可以使用二分法的思想进行解答,先向右移16位再!!,判断数字1是在前十六位还是在后十六位,如果在前十六位,那就让x前前十六位挪到后十六位中,然后再看看是在前八位还是后八位,依次这样,累加移动的位数,对于负数要转化位正数,方法是相反数再减一。

10.求浮点数乘以2的结果

这个题目的函数是unsigned floatScale(unsigned uf)传入的是一个无符号的数,所以我们面临的第一个问题就是将无符号的数转化为单精度浮点数,浮点数是四个字节32位,第一位是符号位,再八位是阶码的值,再23位是尾数,所以我们将无符号数进行与操作在移位就可以了,但是注意要考虑到浮点数的表示方法

11.将浮点数强制转换为整数

我们注意到浮点数的表示范围比整数的表示范围大,所以我们要根据阶码E的大小来分析

12.用单精度浮点数来表示2^x

我们可以通过数轴来理解,要先判断x很小和x很大的时候,也就是能够超出单精度浮点数表示的范围和小于单精度浮点数的范围,然后再确定在中间的范围,确定规格化和非规格化表示的范围

答案

#include<stdio.h>
int bitXor(int x, int y)
{
	return ~(x & y) & (~(x) & ~(y));
}
int tmin(void)
{
	return 0x1 << 31;
}
int isMax(int x)
{
	int tmin = x + 1;
	int equal = (~(tmin) & x);
	return !!tmin & (!equal);

}
int AllOddBits(int x)
{
	int mask_16 = (0xAA << 8)|0xAA;
	int mask_32 = (mask_16 << 8)|0xAA;
	int res = (x & mask_32) ^ mask_32;
	return !res;
}
int negate(int x)
{
	return ~x + 1;
}
int isAsciiDight(int x)
{
	int a = x + (~0x30) + 1;
	int b = x + (~0x39) + 1;
	return ~(a >> 31) & ~(b >> 31);
}
int conditional(int x, int y, int z)
{
	int conditional = !!x;//如果x为0,结果就是0,如果x不为0,结果就是1
	int flag = ~conditional + 1;
	int ret_y = flag & y;
	int ret_z = ~flag * z;
	return ret_y | ret_z;



}
int isLessOrequal(int x, int y)
{
	int sign = y + (~x) + 1;//y-x
	
	//但是要考虑溢出的情况,如果y大于0,x小于0,直接返回1,如果y<0,x>0,直接返回0,如果符号相同那就没有问题
	int sign_x = x >> 31;
	int sign_y = y >> 31;
	int of1 = sign_x & (!sign_y);//x<0,y>0
	int of2 = sign_y & (!sign_x);//x>0,y<0

	return  of1 | ((!sign >> 31) & !of2);

}
int logicNeg(int x)
{
	int negate = ~x + 1;
	return (x | negate) >> 1 + 1;
}
int howManyBits(int x)
{
	int flag;
	int cnt_16, cnt_8, cnt_4, cnt_2, cnt_1, cnt_0;
	int sign = x >> 31;
	x = (sign & (~x) | (~sign & x));//判断x的符号
	flag = !!(x >> 16);
	cnt_16 = flag << 4;
	x = x >> cnt_16;
	flag = !!(x >> 8);
	cnt_8 = flag << 3;
	x = x >> cnt_8;
	flag = !!(x >> 4);
	cnt_4 = flag << 2;
	x = x >> cnt_4;
	flag = !!(x >> 2);
	cnt_2 = flag << 1;
	x = x >> cnt_1;
	cnt_0 = x;
	return cnt_16 + cnt_8 + cnt_4 + cnt_2 + cnt_1 + cnt_0 + 1;
}
unsigned floatScale(unsigned uf)
{
	unsigned s = uf & 0x80000000;//符号位
	unsigned exp = (uf & 0x7f800000) >> 23;//阶码数
	unsigned frac = uf & 0x7fffff;//尾数
	unsigned ret = 0;
	unsigned inf = s | (0xff << 23);
	if (exp == 0xff)//无穷大或者不是一个数,直接返回即可
	{
		return uf;
	}
	if (exp == 0x00)//非规格的数,表示正0或者负0
	{
		if (frac == 0)
			return uf;
		frac <<= 2;
		return s | exp << 23 | frac;
	}
	exp = exp + 1; // 规格化的数,阶码加1就是二倍,根据浮点数的表示方法
	if (exp == 0xff)//阶码加一超过了最大表示的值,直接返回无穷大
	{
		return inf;
	}
	//不超过
	return s | exp << 23 | frac;


}
int floatFloat2int(unsigned uf)
{
	unsigned sign = uf >> 31;
	unsigned exp = (uf & 0x7f800000) >> 23;
	unsigned frac = uf & 0x7fffff;
	int result = 0;
	int E = exp - 127;
	frac = frac | 0x00800000;
	if (E < 0)
		return 0;
	if (E < 31)
	{
		return 0x80000000u;
	}
	if (E > 23)
	{
		result = frac << (E - 23);
	}
	if (sign == 1)
	{
		return (~result) + 1;

	}
	else
		return result;


}
unsigned floatPower2(int x)
{
	int exp;
	unsigned ret;
	if (x < -149)
		return 0;
	if (x > 127)
		return (0xff << 23);
	if (x < -126)
	{
		return 0x1 << (x + 149);
	}
	exp = x + 127;
	ret = exp << 23;
	return ret;
}
int main()
{
	printf("CSAPP--datalab");
}