《深入理解计算机系统》学习笔记(二)2.2~2.3
《深入理解计算机系统》学习笔记(二)
2.2无符号数的编码
假设对于一个w位的无符号整数,用二进制比特位可以表示为[xw-1 , xw-2 , … , x0]。那么我们可以用一个函数表示如下:
每个位Xi都取值为0或1,后一种取值意味着数值2*i应为数字值的一部分。我们看下面的例子。
那么很显然,对于一个无符号编码的数,由 w 位的二进制序列构成,那么它的最小值,即所有位都为 0 ,用位向量表示即:【000…000】。
UMinw = 0
最大值即所有位都为 1,用位向量表示即:【111…111】
UMaxw = 1 * (1-2w) / 1 - 2 = 2w - 1
我们可以得出一个结论:无符号的二进制,对于任意一个w位的二进制序列,都存在唯一一个整数介于0 到 2w-1之间,与这个二进制序列对应。反过来,在0 到 2w-1之间的每一个整数,存在唯一的二进制序列与其对应。
上图中,我们用长度为2*i的指向右箭头的条表示每个位的位置i。每个位向量对应的数值就等于所有值为1的位对应的条的长度之和。可以发现1,2,3,8可以组成十以内的任意数。
二进制 :0101 => 0001+0100 即十进制: 5=1+4
2.3 补码编码
对于许多应用,我们还希望表示负数值。最常见的有符号数的计算机表示方式就是补码(two’s-complement)形式。在这个定义中,将字的最高有效位解释为负权( negativeweight)。我们用函数B2Tw(Binary to Two’s-complement的缩写,长度为w)来表示:
对向量:[xw-1 , xw-2 , … , x0]
其中最高有效位 xw-1 也称为符号位,符号位为 1 时表示负数,当设置为 0 时,表示非负数。我们看下面的例子。
那么我们可以得出:当最高位为1,其余为全部是 0 的时候,即【1000…000】,表示补码格式的最小值:
TMinw = -2w-1
当最高位为 0,其余为全部是 1 时,即【0111…111】,表示补码格式的最大值:
TMaxw = 1 * (1 - 2w-1) / 1 - 2 = 2w-1-1
通过上面的两个公式,我们就很好理解为什么上面C语言数据类型负数的范围要比正数的范围大1。
和上面无符号编码一样,我们对于补码格式编码也可以得到一个结论:
对于任意一个w位的二进制序列,都存在唯一一个介于-2w-1 到 2w-1-1的整数,与这个二进制序列对应。反过来,对于任意介于-2w-1 到 2w-1-1的整数,存在唯一的长度为w二进制序列与其对应。
那么你就应该明白了为什么十进制 -1,在计算机中二进制表示为 1111 1111,而不是1000 0001,因为计算机是以补码的形式表示的。
大家看这张图是不是特别有意思:
有符号数的其他表示方法:
*反码和原码
反码定义:除了最高有效位的权是-2w-1-1,而不是-2w-1其余的和补码表示方式一样
原码定义:最高有效位是符号位,用来确定剩下的位是正还是负。
我们可以和补码的定义进行对比:
原码:一个整数,按照绝对值大小转换为二进制数,最高位为符号位。
反码:将原码除最高位(符号位)外,其余各位按位取反,所得到的二进制码。正数的反码为原码。
补码:反码最低位加1即为补码。
对于正整数,原码、反码、补码完全一样,即符号位固定为0,数值位相同。
对于负整数,原码和补码互相转换的简便方法:从数的右边往左开始数,遇到“0”不理它,直到遇到第一个“1”为止,以后的每一位数取反即是它的原码或补码,符号位不变,还是“1”(补码的补码是原码)。
比如:11010100 ----- 从右往左数,第一位是0,不理它,第二位还是0不理它,第三位是1,那么从此以后的每位取反,即为它的补码了.答案为:10101100
事实上,程序员如果希望代码具有最大的可移植性,能够在所有可能的机器上运行,就应该用补码的形式来表示有符号整数。虽然过去生产过基于反码表示的机器,但是几乎所有的现代机器都是使用补码。
注意:浮点数有使用原码编码。
关于整型数据类型的表示和取值范围,Java标准是非常明确的,它要求采用补码形式,取值范围和C语言在64位机器中的情况一样。在Java中,单字节数据类型称为 byte,而不是char,而且没有long long 数据类型。这些具体的要求都是为了保证无论在什么机器上,Java程序运行的表现都能完全一样。
本文地址:https://blog.csdn.net/weixin_45067072/article/details/109013234
上一篇: Python批量删除mysql中千万级大量数据的脚本分享
下一篇: 菲波那切数列最大公约数