二进制(1):无符号编码和补码编码



一些数学符号的解释:

求和符号:∑5i=0xi=x0+x1+x2+x3+x4+x5

x?  表示向量x ,一组1和0,例如[1010 1100]。

xi此位向量中第i个位。 向量中最右边的位为第0位,向左依次加1.

mod 取模运算 ,求余数运算。 1 mod 2=1 // 3 mod 2=1。在二进制系统中,一个位向量 mod 2k 相当于将此向量截断到k位 。 例如 [1111 1111] (十进制为255)mod 23=[0000 0111](十进制为7)。

111100002=24010 右下角下标表示此数的进制表示格式,例如2为二进制。

B2U。 Binary to Unsigned的简写,既是将二进制位模式通过无符号编码进行解释,转换。此外还有B2T,U2T 之类。

?x? x向下舍入。 ?6.12?=6。

?x? x向上舍入。 ?6.12?=7。



二进制既是将不同长度的“位”(一个1或0)组合在一起再加上不同的解释以赋予含义。同样的机器代码[ 1000 1010] 在不同的编码模式下的意义是不同的。

这里分析一下无符号编码,既是C语言中的unsigned int, 与补码编码,C语言中的 int。通过五个方面进行学习:1,将位模式转换为两种编码格式下的值的过程的函数缩写,2,位向量在两种编码格式下的取值范围,3,位向量在两种编码格式下的扩展方法,4,理解溢出这个现象,并理解如何通过取余运算正确算出溢出后的值,5,了解通过移位替代乘除法这项优化是如何实现的。

最后了解一个变量在两种格式之下的转换发生了什么,以及计算机如何将1和0转换为字符。

1,无符号编码

–函数缩写

如果有位向量 x? 既[xw?1,xw?2,...,x1,x0] ,则在无符号编码中它的十进制值为:

B2Uw(x? )=∑i=0w?1xi2i(公式1)

例如:把[01011110]转换为十进制数值

1,加下标:0716051413121100

2,下标转化为2的幂并乘以相应的位,然后相加:

0?27+1?26+0?25+1?24+1?23+1?22+1?21+0?20=94

–取值范围

假设有一个8位的位向量,最小值无疑是0,它的最大值是 [1111 1111],通过上述公式我们知道它在无符号编码中的十进制值为2的9次方加2的8次方依次到2的0次方,这个2的n的递减次幂的和等于2的n+1次方减1,既2的10次方减1。

所以位向量 [xw?1,xw?2,...,x1,x0] 的取值范围为:

0至2w?1

–扩展

一个通过无符号编码来解释的位向量如果想在不影响它所代表的值的情况下扩展它的位,它的长度,就得在它的最高位之前添加0,这种方法称为零扩展。

例如:将一个较小的无符号数据类型 unsigned short ( 假设为[1111 1100 0011 1111])转换到一个较大的类型 unsigned

在最底层此变量抓换为位向量后将会变为 [0000 0000 0000 0000 1111 1100 0011 1111]

–溢出

已知 w位的位向量的最大值为2w?1。如果编程过程中,赋予它的值超过了此最大值,实际值将会减掉2w。例如,某个变量a的位向量为 [1111 1111] , a+=1 后 理论上它应变为 [1 0000 0000]。 但由于a 只有8位,它无法保存最高位的1,因此实际情况是在底层位向量将会变为 [0000 0000] 。既是赋值给他 [1 0000 0000](29)后减掉了29,变为了0。

加法溢出这种现象是有规律的,可以用取模运算计算变量溢出后的值。

对于一个w位的无符号整数变量a,如果用它储存w位的无符号整数变量b和c的和,那么运算后它的值为:

a=(b+c)mod2w(公式2)

假如b+c= [1111 1111] 小于 2w [1 0000 0000], (b+c)mod(aw) 总是等于他自身,所以公式2试用于所有非溢出情况。另一方面,可计算变量溢出后的实际值,例如变量b [1111 1111] 加c [0000 0101] 等于 [1 0000 0100] 溢出后 为 [0000 0100] (254+5)mod(2w) 会得4, 等于[0000 0100],既溢出后a实际的值。

用取模运算计算减法溢出后的值:

设一个w位的无符号整数变量a,如果用它储存w位的无符号整数变量b和c的差,则:

a=(b+(2w?c))mod2w(公式3)

例如b=[0000 0000] , c=[0000 0001], 得出的结果将为 2w?1

用取模运算计算乘法溢出后的值:

设一个w位的无符号整数变量a,如果用它储存w位的无符号整数变量b和c的积,则:

a=(b?c)mod2w(公式4)

例如:b=5 [101],c=3[011]在无符号编码下它的值为[101]*[011]=[1 111], 溢出后为[111]

15mod23=7[111],公式计算结果与实际值一致。

–用移位替代乘法和除法

无符号整数的乘法,除法相对于加减法,移位,位级运算来讲是很慢的。乘法可以被移位操作和加法的组合替代掉。

1,左移代替乘法。

已知一个位向量 x? ,[xw?1,xw?2,...,x0]。如果在它的最低位添加k个0,则它会变为,[xw?1,xw?2,...,x0,0,...,0]

计算这个位向量的十进制值的公式是上面的公式1的一种变形,由于xk至x0都是0,求和公式并没有太大的改动,只是公式1中的每个位都要再乘以2k,既变为了 :

∑i=0w?1xi2i+k=(∑i=0w?1xi2i)?2k(公式5)

结论: x? ?2k 等于在位向量的低位添加k个0 ,也既是整个位向量向左移k位。

例:

x? ?10=x? ?(23+2)=x? <<3+x? <<1

x? ?5=x? ?(22+1)=x? <<2+x?

2,右移代替除以2的幂

设位向量 x? ,[xw?1,xw?2,...,x0]

设 k 为 0≤k<w

设 x,为一个w-k位的位向量[xw?1,xw?2,...,xk]

设x″为[xk?1,...,x0]

根据公式1对x,x,,x″进行求和:

x=∑i=0w?1xi2i(公式6?1)

x,=∑i=kw?1xi2i?k(公式6?2)

x″=∑i=0k?1xi2i(公式6?3)

将公式6-2乘以2k得出:

x,=∑i=kw?1xi2i(公式6?4)

而公式6-4(2kx,)加上公式6-3等于公式6-1,也既是x,所以:

x=2kx,+x″(公式6?5)

再观察公式6-3,位向量最小值为 [00…0], 最大值为[11…1],此最大值的求和公式为∑k?1i=02i=2k?1。

所以x″ 的取值范围是0≤x″≤2k?1或0≤x″<2k。

由于x″总是整数并且总是小于x″,那么x″/2k一定是一个小于1的小数,向下舍入总是得0:

?x″/2k?=0(公式6?6)

公式6-5两边除以2k并向下舍入,得?x/2k?=?x,+x″/2k?,因为x,为整数,x″/2k又一定为一个小数,所以等式右边舍入后既是x’。

?x/2k?=x,(公式6?7)

再考虑下如果对位向量x进行右移k位的操作,[xw?1,xw?2,...,x0]右移k位会得到[0,...,0,xw?1,xw?2,...,xk],位移后的向量实际上就是上面的x,。

结论:对于位向量x,[xw?1,xw?2,...,x0]右移k位等同于x/2k。

无符号整数的除法也可以用向右移位来替代,但只局限于除以2的幂的情况。

[0000 1100]=12

右移两位

[0000 0011]=3

12÷22=3

2,补码编码

–函数缩写

补码编码的最高有效位(xw?1)为负权,它表示的是xw?1?(?2w?1)。当它为1时,它将会减去后面的正数之和,通过这种方式表示负数。当它为0时,0?(?2w?1)为0,位向量的值为正数。

公式: 如果有位向量 x? 既[xw?1,xw?2,...,x1,x0] ,则它在补码编码中的值为:

B2Tw(x? )=?xw?12w?1+∑i=0w?2xi2i(公式7)

–取值范围

w位补码的最小值为[100…0]既是 ?2w?1,最大值为[011…1] 既是∑w?2i=02i。

这种编码模式又造成了一种现象。考虑一下 23?(22+21+20)=1 我们发现 xw总是比∑w?1i=0xi 大1,因此 w位补码 的最小值的绝对值 总是比 它的最大值大1。正负数两端并不是对称的。

–扩展

与无符号编码的扩展方式不同。由于最高有效位为负权,在不改变位向量的值的情况下对它进行扩展的方法叫做符号扩展,考虑一个位向量[1111 1111] ,它的值为 27?26?25?...20=1。符号扩展一位后为[1 1111 1111] ,它的值依然为1,根据此数学规律,在位向量为负数的时候,既是最高位为1的时候,在它的最高位左边添加1不会影响它的值。而在位向量为正数时,在最高位左侧添加0,同等于上面无符号编码中的零扩展,也不会改变它的值。

这种在补码编码中对变量进行扩展的方式称为符号扩展—–在最高位左侧添加最高有效位的副本。

–溢出

补码编码的溢出除了考虑赋予变量的值超出它能表示的最大值的情况外,还要考虑赋予它的值超出了它能表示的最小值的情况。

设有w位的有符号整数变量a [aw?1,aw?2...a1,a0]

a的取值范围为?2w?1≤a≤2w?1

补码加法溢出与无符号编码相同现,可以用取模运算计算变量溢出后的值。

对于一个w位的变量a,它储存w位的变量b和c的和,那么运算后它的值为:

a=(b+c)mod2w(公式8)

但 补码编码的溢出除了考虑赋予位向量的值超出它能表示的最大值的情况外,还要考虑赋予它的值超出了它能表示的最小值的情况。

(b+c)mod2w=?????b+c?2wb+cb+c+2w2w?1≤b+c?2w?1≤b+c<2w?1b+c<?2w?1(公式9)

例如:b=-1[1111 1111] c=-128[1000 0000]

b+c=[1 0111 1111]=-129

溢出后为 [0111 1111]=127

根据公式11的条件3,公式10计算结果为:(b+c)+2^w=-129+256=127

减法溢出:

对于一个w位的变量a,它储存w位的变量b和c的差,那么运算后它的值为:

a=(b?c)mod2w(公式10)

(b?c)mod2w=?????b?c?2wb?cb?c+2w2w?1≤b?c?2w?1≤b?c<2w?1b?c<?2w?1(公式11)

例如b=-128[1000 0000] c=1[0000 0001]。

位向量相减得 b-c=[0111 1111] ,127。

公式10计算结果,根据公式11情况3,b?c+2w=?128?1+256=127。

用取模运算计算乘法溢出后的值:

设一个w位的有符号整数变量a,它储存w位的有符号整数变量b和c的积,则:

a=(b?c)mod2w(公式12)

–用移位替代乘法和除法

1,左移替代乘法

无符号编码中的公式5对补码编码依然通用,既:

∑i=0w?1xi2i+k=(∑i=0w?1xi2i)?2k(公式5)

结论: 有符号整数x?2k 等于在位向量的低位添加k个0 ,也既是整个位向量向左移k位。

2,右移代替除以2的幂

在无符号编码中,代替除法的右移为逻辑右移,既在最高位添加0。

对于一个最高位负权为0的有符号整数,逻辑右移的效果是一定与无符号整数一致的。但是如果最高位负权为1,最高位添加0肯定是错误的,负数将会变为正数。因此替代的方法为算术右移。设x为有符号整数变量x,整数k为 0≤k<w, x,为截取x w-k位的有符号整数,x”为截取x低k位的无符号整数,用无符号编码部分相同的逻辑可以推理到公式6-5,x=2kx,+x″(公式6?5) ,两边除以2k得x/2k=x,+x″/2k,但是再进一步分析就要考虑x为负数的情况了:

1,x为正数

x,为x移位前左边部分截取的位向量,它的值是我们算术右移后应该得到的值,它的负权位与x的负权位是一致的, x″为x的位向量的低k位的无符号数,设为无符号数是因为它代表的是x移位前低k位的值。x″/2k一定是一个小于1的小数,那么可以把x=2kx,+x″(公式6?5)两边同时向下舍入得出?x/2k?=x,(公式6?7),此公式的意义既是有符号整数x除以2k等于算术右移k位。这些内容等同于无符号编码的部分。

2,x为负数

x,为x移位前左边部分截取的位向量,它的值是我们算术右移后应该得到的值,它的负权位与x的负权位是一致的, x″为x的位向量的低k位的无符号数, 设为无符号数是因为它代表的是x移位前低k位的值。公式6-5两边除以2k得x/2k=x,+x″/2k,现在,2k一定为正数,如果x为负数,那么x/2k为一个负数,由于我们想要的实现的整数除法的结果是舍去小数部分的整数,一个负数向下舍入将会改变整数部分,例如-3.14向下舍入将会得到-4,这里应该向上舍入得-3。但是实际上代码的整除除法的结果总是向下舍入,因此须找到一个能达到?x/2k?效果的某种向下舍入的方法。

设x=k?2k+r,0≤r<2k,k代表x除以2^k后的整数部分, r代表x除以2k后的余数部分。

两边同时加2^k-1再除以2^k并向下舍入:

?(x+2k?1)2k?=?k+r+2k?12k?(公式13)

当r=0时,既x没有小数时,?2k?12k?一定等于0,公式13左边部分等于x的整数部分。

当r>0时,由于r<2k,?r+2k?12k?=?2k2k?+?r?12k?=1+0=1。公式13左边部分等于x减去小数部分,整数部分加一。

因此?(x+2k?1)2k?既是我们想要的转换?x/2k?的方法。

将2k转换成移位,2k=1?2k=1<<k。

3,结论:对于有符号整数变量x,除以2k,等同于对它的位向量[xw?1,xw?2,...,x0]进行以下的移位操作:

(x<0?(x+(1<<k)?1):x)>>k(公式14)

–有符号数和无符号数之间的转换

设一个无符号数变量x,它的位向量是 [1111 1111],它的值为255。

将变量x强制转换为有符号格式,它的位向量不发生任何改变,依然还是[1111 1111],在补码编码下,它的值为-1。

考虑一下它的值的变化,在无符号编码下,它的值为23+22+21+20,在补码编码下,它的值为?23+22+21+20,所以x在由无符号变量转换为有符号变量的过程中,它的值减少了两个23,反过来讲既是,x在由有符号变量转换为无符号变量的过程中,它的值增加了两个23,如果设x的位向量为w位,[1w?11w?21110],两个23既是两个2w?1,两个23等于24,两个2w?1等于2w。将这个变换转为数学公式:

T2Uw(x)=xw?12w+x(公式15)

U2Tw(x)=x?xw?12w(公式16)

在由无符号变量转变为有符号变量后,当x的最高位,w-1位,负权位为1时,它自身的值会增加xw?12w,当他的最高位w-1为0时,它的值 保持不变。反之亦然。

ASCII字符

假设有位向量 [0100 0001]

通过无符号编码解释,此向量代表65。

通过补码编码解释,此向量代表65。

通过ASCII字符码解释,此向量既是代表 “A”。

因此在C语言中,将一个被赋值“A”的char变量用%d 打印出来的结果将会为“65”。

ASCII码表中的127个打印字符分别对应[0000 0000]至[0111 111]的位向量。由于不涉及到最高有效位,所以在c语言中声明一个 char a=”A”;不管是用%d还是%u格式打印,输出都会是65。

附:

十六进制Hexadecimal/十进制Decimal/二进制Binary(无符号编码) 对应表

Hex 0 1 2 3 4 5 6 7 8 9 A B C D E F
Bin 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
Dec 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

学习资料:深入理解计算机系统(原书第二版 )—Randal E.Bryant

时间: 2024-10-10 21:13:03

二进制(1):无符号编码和补码编码的相关文章

深入理解计算机系统(2.4)------整数的表示(无符号编码和补码编码)

上一篇博客我们主要介绍了布尔代数和C语言当中的几个运算符.那么这一篇博客我们主要介绍在计算机中整数是如何表示的,诸如我们在编码过程中遇到的对数据类型进行强制转换可能会得到意想不到的结果在这篇博客里你会得到解答. 1.什么是整数? 整数包含正整数,0,负整数.我们从小的数学常识,整数是无穷无尽的,即整数的大小没有限制. 但是在计算机中则不能这样理解,因为计算机是靠数字信号来表示数,计算机所能处理的整数的长度是由计算机的字长来决定的,所以,在计算机中,我们必须制定一个规则来表示整数. 2.C 语言中

0阶 无符号指数哥伦布编码

指数哥伦布编码与哈夫曼编码一样都属于变长编码 但二者也有显著的区别: 1>信源相关性: 哈夫曼编码依赖于信源的概率分布,而指数哥伦布编码与信源无关 2>额外信息: 哈夫曼编码必须携带与该信源匹配的码表,指数哥伦布编码无需携带额外信息 h264官方协议文档中定义了4类指数哥伦布编码分为: ue(v)无符号指数哥伦布编码 .se(v)有符号指数哥伦布编码. te(v)截断指数哥伦布编码 和 me(v)映射指数哥伦布编码 下面我们截取了协议文档中 ue(v)无符号指数哥伦布编码的部分作为例子来分析,

关于有符号整数的补码编码的一点经验

以一个字节(8位)编码为例,如果采用补码,则表示的整数(有符号数)范围是[-128,127]. 如果把该二进制编码表示为十进制,则8位编码对应的十进制为0-255,(或者说表示为无符号数就是0-255) 其中[0-127]表示正整数,也是该数本身(对应的无符号数和有符号数一样且都是正整数),绝对值递增 [128-255]表示负整数,其中128表示-128 ,255 表示 -1,也就是说绝对值是递减的. 所以根据编码快速求出编码前的数的方法之一是:如果编码为0-127,那么编码前的数也是0-127

二进制的原码反码补码

原码是什么? 原码就是早期用来表示数字的一种方式: 一个正数,转换为二进制位就是这个正数的原码.负数的绝对值转换成二进制位然后在高位补1就是这个负数的原码 举例说明: int类型的 3 的原码是 11B(B表示二进制位), 在32位机器上占四个字节,那么高位补零就得: 00000000 00000000 00000000 00000011 int类型的 -3 的绝对值的二进制位就是上面的 11B 展开后高位补零就得: 10000000 00000000 00000000 00000011 但是原

C语言的有符号与无符号,二进制整数的扩展与截断

前一节说了整数的表示方式,,也就是无符号编码与补码编码.这一届说一下二进制整数的扩展与截断,这部分内容与C语言挂钩.so,我们先看以下C语言的有符号和无符号数. C语言中的有符号数和无符号数 有符号数和无符号数的本质区别其实就是采用的编码不同,前者采用补码编码,后者采用无符号编码. 在C语言中,有符号数和无符号数是可以隐式转换的,不需要手动实施强制类型转换.不过也正是因为如此,可能你一不小心就将一个无符号数赋给了有符号数.就会造成出乎意料的结果,就像下面这样: #include <stdio.h

二进制整数的乘除运算

前言 运算一直视程序运行当中一个重要的环节,而在二进制的运算过程当中,加法运算有时重中之重,他基本上奠定了二进制运算的基础.因此无论是减法还是乘法,都可以由加法运算来代替,唯独除法不能代替. 了解了计算机运算的规律,可以有助于我们理解很多程序代码上无法理解的内容能够.比如上一张提出的溢出问题,在了解了加法运算的原理之后,相信大家都可以轻松您的知道为何有些运算会得到意想不到的结果. 这里还需要提到一点,不同的处理器所采取的运算方式可能有细微的差别,因此也不能一概而论.因此我们大多数时候会尽量讨论运

信息安全系统设计基础 第4周学习笔记

信息的表示和处理 一.信息存储 ① 3种数字的表示:无符号编码.补码编码.浮点数编码. ② 二进制.八进制.十六进制转化 ③ 字:字长为w位,虚拟地址范围为0~2^w-1,程序最多访问2^w个字节. 数据大小:(short.long)int.char.long long.float.double ④ 寻址和字节顺序:  小端法:最低有效字节在最前面的方式(大多数Intel兼容机) 大端法:最高有效字节在最前面的方式(大多数IBM和Sun Microsystems) 双端法:可以设置其中一种. ⑤

整数的表示方式精解

这一届比较重要,不对,是很重要.上一次我们说了布尔代数以及C语言的位运算. C语言中的整数类型以及范围 以C语言为例,C语言当中提供了多种整数类型,一共始终,位数为1,2,4,8,其中32位机器上,4位的有两种,64位的机器上,8位的有两种.下面是32位OS上,这十种整数的范围: 32位的系统不常见了,来看一下64位OS上的范围: 说实话,差不多,你不用背过. 上述是C语言中各个整数类型的表示范围,不过C语言有他的最小数值范围,也就是说C语言要求这些数据类型至少要满足一个标准的范围.下图是C语言

深入理解计算机系统(2.5)------C语言中的有符号数和无符号数以及扩展和截断数字

上一篇博客我们讲解了计算机中整数的表示,包括无符号编码和补码编码,以及它们之间的互相转换,个人觉得那是非常重要的知识要点.这篇博客我们将介绍C语言中的有符号数和无符号数以及扩展和截断数字. 1.C语言中的有符号数和无符号数 上一篇博客我们给出了C语言中在32位机器和64位机器中支持的整型类型数据,我们这里只给出32位机器上的: 尽管 C 语言标准没有指定有符号数要采用某种编码表示,但是几乎所有的机器都使用补码.通常大多数数字是默认有符号的,比如当声明一个像12345或者0xABC这样的常量的时候