Datalab实验_Lab1

Lab1

question1

  • 题目:
    给予⼀个整数 x ,如果它乘 2 之后会溢出则返回 0 否则返回 1
    例如: question1(0x20000000) = 1
    例如: question1(0x40000000) = 0
  • 思路:
    题目要求判断输入的整数x乘以2后的结果是否溢出,可以视为判断加法运算是否溢出,加法会产生溢出的情况是当两数相加的时候符号异号,即x与2x的符号不同,因此可以通过判断x乘以2前后的符号是否改变来判断是否出现溢出,所以通过异或’^'运算判断符号是否相同,但是题目要求的是当溢出的时候返回0,所以还需要对其结果进行处理。
  • 代码:
int question1(int x) {
	x = ~((x^(x<<1)>>31) )& 0x1;
	return x&0x1;
}

question2

  • 题目:
    给予三个数 x 、 y 和 n ,比较 x 和 y 的第 n 字节,如果相同则返回 0 ,不同则返回 1 。
    例如: question2(0x12345678, 0x87654321, 1) = 1
    例如: question2(0x12345678, 0x87344321, 2) = 0
  • 思路:
    题目要比较x 和 y 的第 n 字节,相同返回0。一个整数有32位,共4个字节,所以一个字节有8位,n应该乘以8,然后先把x,y分别右移8n位后再与0xFF进行与运算保留当前位置下x,y的末8位,最后再判断末8位的结果是否相等。
int question2(int x, int y, int n) 
{
	int a = 0x0, b = 0x0, c = 0x0;
	c = 0xFF>>(n<<3);//这样不好求(a,b移位不对齐)
	a = (x & c)&0x1;
	b = (y & c)&0x1;
	return !(!(a^b));
}

这样通过x,y与分别与c向与在与和0x1相与得到的a,b会出现两数位数不等不好比较的情况,所以先移动x,y的值(而不是移动0xFF)再比较。

  • 代码
int question2(int x, int y, int n) {
	n <<= 3;// n乘以8才能表示右移的位数
	x = (x>>n)&0xFF;// 与0xFF相与表示保留x的末8位,即x的第n个字节
	y = (y>>n)&0xFF;
	return !(!(x^y));
}

question3

  • 题目:
    给予两个数 x 和 y ,如果 x<=y 则返回 1 ,否则返回 0 。
    例如: question3(4,5) = 1
    (提示:可以利用eflags 的思想来做)

  • 思路:
    题目要比较x 和 y 的大小,即比较x<=y,成功返回1。题目提示使用eflags 的思想来做,所以我想通过判断y - x运算的标志位,ZF(零标志位)与CF(进位/借位标志位)

      当x == y时:ZF == 1,CF未知;
      当x > y时:ZF == 0,CF == 0;
      当x < y时:ZF == 0,CF == 1;
    

    而且结果要分为同号和异号来判断。

  • 代码:

int	question3(int x, int y) {
	int ZF = 0x00, CF = 0x00;// 通过zf、cf的值比较大小
	int a = (x>>31)&0x1;// 求出x、y的符号(0/1)
	int b = (y>>31)&0x1;
	CF = !(a^b);// CF用来判断两数符号是否相等
	ZF =(!(((~x+1)+y)>>31))&0x1;// ZF判断两数大小是否相等
	return ((CF&ZF)|((!CF)&a));// (!CF)&a) 判断CF与a是否同号
}

question4

  • 题目:
    给予⼀个整数 x , 如果该整数的⼆进制形式包含奇数个 1 则返回 1 ,否则返回 0 。
    例如: question4(5) = 0, question4(7) = 1

  • 思路:
    题目要判断二进制整数中’1’的个数的奇偶性,奇数返回’0’。

    这题挺难的,需采用的分治算法解决。

    取出x的不同位置上的’1’个数,再对其判断奇偶。而如何取出x中的’1’?首先使用特别的掩码依次求出不同位置上’x’的’1’的个数,代码如下:

/*分治算法 编辑
分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。即一种分目标完成程序算法,简单问题可用二分法完成。*/
/* 要求x的二进制中的'1'的个数,可以通过x的奇数位上或偶数位上是否存在着'1'来判断,即:通过掩码屏蔽不同位上的数字,在进行运算的得到'1'的个数,最后判断奇偶*/
int temp = 0x0, mask_1 = 0x0, mask_2 = 0x0, mask_3 = 0x0, mask_4 = 0x0, mask_5 = 0x0;
temp = (0x55<<8) | 0x55;//   16位0101...掩码
mask_1 = (temp<<16) | temp;//32位0101...掩码,即:0x55555555;
temp = (0x33<<8) | 0x33;
mask_2 = (temp<<16) | temp;//32位0011...掩码,即:0x33333333;
temp = (0x0F<<8) | 0x0F;
mask_3 = (temp<<16) | temp;//32位00001111...掩码,即:0x0F0F0F0F;
mask_4 = (0xFF<<16) | 0xFF;//32位掩码,即:0x00FF00FF;
mask_5 = (0xFF<<8) | 0xFF;// 32位掩码,即:0x0000FFFF;

/*通过上面求出来的一系列掩码与x进行位运算,相当于把x中'1'的个数的信息移动到最后面的位置*/
x = (x & mask_1) + ((x >> 1) & mask_1);
x = (x & mask_2) + ((x >> 2) & mask_2);
x = (x & mask_3) + ((x >> 4) & mask_3);
x = (x & mask_4) + ((x >> 8) & mask_4);
x = (x & mask_5) + ((x >> 16)& mask_5);

但是运行的时候显示运算符超出了界定的范围(因为限定了使用的常数的大小,不能直接写出需要的掩码,需要进行转换,所以超出了范围), 所以改为不使用掩码,直接对x进行处理;

  • 代码:
int question4(int x) {
	x = x^(x>>1);// 求出2位x的'1'的个数
	x = x^(x>>2);// 求出4位x的'1'的个数
	x = x^(x>>4);// 求出8位x的'1'的个数
	x = x^(x>>8);// 求出16位x的'1'的个数
	x = x^(x>>16);// 求出32位x的'1'的个数
	return x & 0x1;
}

eg:当x = 0111时:(4位,只运行到第二行);

    x = 0 1 1 1    异或的结果是:x = 0100
x >>1 = 0 0 1 1
       
     x = 0 1 0 0   异或的结果是:x = 0101 --> x = 3: x中有3'1'
x >> 2 = 0 0 0 1  

question5

  • 题目:
    给予⼀个无符号整数表示的浮点数 uf (你可以认为 uf 具有浮点数的比特级结构) ,函数返回它的相反数,即 -f (返回的结果也是⼀个无符号整数表示的浮点数),如果这个数是 NaN ,请返回它本身。
    *思路:
    题目要求出浮点数uf的相反数-f。求出浮点数uf的相反数要注意浮点数中的NAN的表示(NAN表示非法的数,当阶码部分全为1且小数部分不全为1时表示NAN,对于单精度浮点数来说,NAN就是0x7FFFFFFF),当不是NAN是返回uf,求相反数就是用uf与0x80000000异或。
  • 代码:
unsigned question5(unsigned uf) {
	if((uf&0x7FFFFFFF) <= 0x7F800000)//此时为非NAN的情况(NAN是指浮点数的指数全1,小数部分大于0,若小数部分为0则为无穷infinity
		uf ^= 0x80000000;
	return uf;
}

question6

  • 题目:
    给予⼀个无符号整数表示的浮点数 uf (你可以认为 uf 具有浮点数的⽐特级结构) ,函数返回它对应的强制类型转换后的整数(具有整数的比特级结构),即实现表达式 (int)uf ,如果这个数超过整数表示的范围(包括 NaN 和无穷),请返回 0x80000000u 。

  • 思路:
    题目要求是将浮点数表示为整数。解决这个题目的思路就是通过位运算求出浮点数的符号、阶码、小数,在根据不同的情况做处理。

      s = 符号  E = 阶码  M = 尾数 ——>   V = (-1)^S * M * 2 ^ E;
    

    其中,浮点数为规格化数:(阶码既不为全0,也不为全1)(单精度浮点数的exp的范围是-126 ~ 127)

      ​M = 1 + frac     frac为浮点数的小数部分的值(1是隐含位)
      E = exp - Bias  exp为浮点数的阶码 Bias = 2^k - 1(单精度浮点数为127)
    

    浮点数为非规格化数: (阶码为全1)

      M = frac
      E = 1 - Bias
    

    而且,对于浮点数,当exp与frac全为0时浮点数为0;当exp为全1,frac为全0是表示浮点数无穷infinity;
    当exp与frac全为1是表示浮点数NAN(NAN与NAN不相等)

  • 代码:

int question6(unsigned uf) {
	int exp = (uf>>23)&0x000000FF;// 求出阶码(第2~9位)
	int frac = (uf & 0x000000FF) | 0x00800000;//求出小数部分(第10~32位)
	unsigned sign = (uf>>31)&0x1;// 符号
	if(sign == 0) sign = 1;
	else if(sign == 1) sign = -1;
	if(exp >= 0xFC)// 当uf为非规格化数时 (NAN,infinity等)
		return 0x80000000;
	else if((frac == 0x00 && exp == 0x00) | (exp <= 0x02))// 当uf可能为0时
		return 0x00;
	uf = (frac + 1) >> (23 - exp + 127);// 求值
	return sign*uf;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值