《深入理解计算机系统》第二章习题2_66

最近打算把《深入理解计算机系统》再读一遍,说实话这本书读多少遍都不嫌多,每读一遍都会有收获。这次决心把书中的习题整个过一遍,并把其中我认为比较典型的、有意思的写城博文记录一下,恩,这就是这篇博文的由来。恳请各路大神拍砖。

一. 问题描述(鉴于我这不忍直视的翻译水平,我就直接贴书中的问题描述了):

Generate mask indicating leftmost 1 in x. Assume w = 32.

For example 0xFF00 -> 0x8000, and 0x6600 --> 0x4000.

If x = 0, then return 0.

int leftmost_one(unsigned int x);

二. 结果正确但不符合题意的解决方法:

刚开始看到这个问题,想了想,突然间有了一个很简单的解决方案,所以赶紧写代码试了一下,恩,效果不错,所得结果是正确的。(窃喜),但再仔细看题目要求,这和说好的不一样啊!!帖代码:

int leftmost_one(unsigned int x)
{
	unsigned int base = 0x80000000;
	while(base)
	{
		if((x & base))
			break;
		base >>= 1;
	}
}

意思很简单,既然题目中假设w=32,那么我想,只需要从32位下最大的数base开始和x进行与运算,如果结果不为零,那么这个base就是x中最左边的那个1所表示的数了。

三. 分析:

题目的要求是,让我们生成一个掩码,用来标识出x中最左边的那个1。(换句话说是让我们找到一个掩码,使得x除了最左边为1的那一位,别的位都置为0),很遗憾我们上面的代码并没有产生任何叫掩码的东西。以下来分析一下这个问题:

书中题目下方有个小提示,“把x转换成形如 000...111..的形式”,好吧,竟然是这么含蓄的提示。

假设此时的字长w = 8,假设 x = 00010110,那么结果必然为 0001 0000,什么样的掩码能达到这个效果呢,我们想到了这个mask = xxx1 0000,(x 既可以为0,也可以为1)

那么 x & mask = 0001 0110 & xxx1 0000 = 0001 0000。现在问题的关键就是怎么才能由x生成这个掩码mask:(我们这时要想一想那个含蓄的提示了)

在x中最左边的1左边的位全为0或者没有,那么我们可以通过位运算把最左边的1右边的所有位都置为1(好拗口),如下:

0001 1111

然后在此基础上取反,有:1110 0000,然后再右移一位,有 0111 0000,哈哈,此时我们的掩码就生成了。帖代码:

int leftmost_one(unsigned int x)
{
	unsigned int mask = x;
	mask |= mask >> 1;
	mask |= mask >> 2;
	mask |= mask >> 4;
	mask |= mask >> 8;
	mask |= mask >> 16;
	mask = (~mask) >> 1;
	return x & mask;
}
时间: 2024-08-24 20:16:07

《深入理解计算机系统》第二章习题2_66的相关文章

CSAPP深入理解计算机系统第二章荟萃

1.可以利用数字的算数右移,然后利用0XFF这样的数字做掩码运算,可以获取到一个数字的符号位.计算机的移位运算有一种很重要的作用就是利用掩码运算去提取一个位模式的一段信息. 2.在C语言中的条件语句,以及三目的条件运算符,都可以用移位的方式来做. 3.在进行位扩展操作的时候,比较讲一个32位的有符号数扩展到64位,那么在保证原来的值不变的情况下,把31个低位扩展到64位的低位上,而最高的符号位扩展到高33位上. 4.利用位模式仅仅只能表示一些2的n次幂的一些浮点数,其他的比较特殊的有理数,会近似

深入理解计算机系统 第二章 信息的表示和处理

欣哥划重点: @所有人, 第二章比较难,我建议至少掌握下面几个知识点: 1. 字节顺序 : 大端和小端 2. 运行 图2-24, 图2-25程序 show-bytes.c 观察结果,看看有什么问题 3. 理解布尔运算,位运算 4. 理解无符号数和有符号数, 给一个数,能计算出补码 5. 理解浮点数的表示法,给一个十进制小数,能转换成二进制的浮点数表示 原文地址:https://www.cnblogs.com/stone94/p/9824395.html

深入理解计算机系统 第二章要点

1.每台机器都有一个字长,指明了整数和指针的标称大小(normal size),长整数(long int)和指针的大小都是字长(32位机器是32位,64位机器是64位),字长代表了机器的寻址时地址大小,进而限定了寻址空间的大小,字长w的寻址范围是0-2的(w-1)次方,32位机上线是4G.除了和字长同步的类型(long int和指针)其他类型大小和机器无关,比如char,short,int4,long long int8, float4, double8在32位机器上对8字节的类型数据操作时,先

深入理解计算机系统-第二章

疑惑: ***."十进制数字x的ASCII码正好是0x3x"(p31) ```.照上面这么说,十进制1的ASCII码该是0131,很明显错误的,找到一个ASCII码来看下"1"的ASCII码是"49", 再仔细参考下书中上下文,发现上面说了十进制1的ASCII码是31,那原句这么说"十进制数字_x的ASCII码正好是0x3_x"是不是更好理解点, 避免"x"的理解错误,你可能又会说,现在还是不对啊,现在1的

深入理解计算机系统 第二章 信息的表示和处理 part2

上一周遗留问题的解决 问题:原码.反码.补码是只针对有符号数吗?无符号数有没有这三种编码方式? 得到的答案:对于无符号数,原码.反码和补码是一致的 进一步,由于有符号数是以补码的形式存储在计算机中的,而无符号数三种编码都是一致的,所以我们可以说,整型数在计算机中是以补码的形式存在的. 参考文章: https://www.jianshu.com/p/ffc97c4d2306 浮点数 对于浮点数,看了刘大的文章<看完这篇文章,你肯定理解什么是浮点数了>之后,知道了两点 1.浮点数是如何存储的 2.

深入理解计算机系统第二版习题解答CSAPP 2.13

从20世纪70年代末到80年代末,Digital Equipment的VAX计算机是一种非常流行的机型.它没有布尔运算AND和OR指令,只有bis(位设置)和bic(位清除)这两种指令.两种指令的输入都是一个数据字x和一个掩码字m.它们生成一个结果z,z是由根据掩码m的位来修改x的位得到的.使用bis指令,这种修改就是在m为1的每个位置上,将z对应的位设置为1.使用bic指令,这种修改就是在m为1的每个位置,将z对应的位设置为0. 只使用这两个函数实现C语言的按位|和^运算. 1 int bis

深入理解计算机系统第二版习题解答CSAPP 2.6

使用打印字节的方式可以知道十进制数12345的十六进制为0x00003039,十进制浮点数12345.0的十六进制为0x4640E400. 转换为二进制为 1 /* 2 0 0 0 0 3 0 3 9 3 00000000000000000011000000111001 4 ************* 5 4 6 4 0 E 4 0 0 6 01000110010000001110010000000000 7 8 */ 移动后有13位匹配. 已知十进制数3510593的十六进制为0x003591

深入理解计算机系统第二版习题解答CSAPP 2.12

对于下面的值,写出变量x的C语言表达式.代码应该对任何字长w≥8都能工作.我们给出当x=0x87654321以及w=32时表达式的结果,仅供参考. A.x的最低有效字节,其他位均为0.[0x00000021]. B.除了x的最低有效字节外,其他位都取补,最低有效字节保持不变.[0x789ABC21]. C.x的最低有效字节设置成全1,其他字节都保持不变.[0x876543FF]. 解答: A. x & 0xFF B. ~(x ^ 0xFF)或者(~x) ^ 0xFF C. x | 0xFF

深入理解计算机系统第二版习题解答CSAPP 2.18

将32位补码表示的数转换为10进制数. 32位补码 十进制 0x1b8 440 0x14 20 0xFFFFFE58 -424 0xFFFFFE74 -396 0x44 68 0xFFFFFEC8 -312 0x10 16 0xC 12 0xFFFFFEEC -276 0x20 32