bit、数据类型及其运算

bit和数据类型

bit—信息的基本单位

我们知道,计算机是一个包含了多层转换的系统。一个由自然语言(如英语)描述的问题,最终必须转换为计算机内部的电路工作(更具体的说是电子运动),才得以解决。

注:若不理解多层转换的系统,可以参考我之前写的文章,文章链接如下:

计算机系统简述-@邂逅自己icon-default.png?t=N7T8https://blog.csdn.net/2302_76708905/article/details/140237885?spm=1001.2014.3001.5502在计算机内部,有数以百万计的器件在控制着电子的运动。这些器件随时监测着电路中各处电压的变化,并做出不同的响应控制。它们不仅监测电压的有无,甚至还能真正测量电压的大小,但这无疑会导致控制和检测电路的过度复杂性。如果只需要检测电路中任意两点间是否有电压,而不是测量其精确电压值,电路的复杂性无疑会大大降低。

在符号层义上,我们采用“1”表示两点间存在电压,而“0”表示两点间不存在电压。我们称这样一个要么是“1”,要么是“0”的符号单位为一个bit,即所谓的二进制表示方法。确切的说,计算机对有电平(即“1”)和无电平(即“0”)并不做严格的电压值定义。换句话说,“0”并不表示电路中就绝对不存在电压,它仅仅表示当前“0”所代表的电压值比“1”所代表的电压更接近于电压值“0”。同样,“1”表示它所代表的电压值与电压0的差值很大。例如,计算机定义2.9V的电压表示“1”,而0V电压表示“0”。但如果电路实际测得的电压值为2.6V,计算机也会将它当做“1”来处理;同样,如果实际测得的电压值为0.2V,计算机则将它当做“0”。

当然,计算机需要定义足够大的数值范围才能工作。但事实上,电路只有两个状态,即有电压(用“1”表示)和无电压(用“0”表示)。为了表示更多的数值状态,我们可以将多条线路合并使用,比如8个bit宽度(即8条线路),这样就可以表示256个不同的状态(即00000000~11111111)。通常,k个bit的组合可以表达(2^k)个不同状态,每个状态分别是k个0和1的bit序列组合。我们称该0和1的序列为编码,每个编码对应一个特定的值或状态。

数据类型

数值的表达方式多种多样(如:计算机采用的二进制表示法、科学计数法等),只是能够表达“数值”还是不够的,计算机还必须具备操作这些数值的能力。如果我们不仅定义了数值的表达方式(或编码方式),同时还定义了相关的操作方法,则在定义上称该表达方式为一种数据类型。每个计算机指令集(ISA)都定义了一组数据类型及其相应的操作指令,数据类型的数目可多可少(取决于ISA的设计要求)。本栏目中,我将在算术运算中采用补码编码表示正、负整数,在键盘输入和显示器输出的应用中,采用ASCII字符。

整数数据类型

无符号整数(unsigned integer)

无符号整数在计算机中的应用非常广泛。比如我们希望限定一个任务的执行次数,使用一个无符号整数即可,用它来记录该任务还有多少次执行次数。另外,我们还可以使用无符号整数表示不同内存单元的地址,这与日常生活中的用法很相似,如第129号大街或第131号大街。有k个bit则可以表示(2^k)个无符号整数。

有符号整数

在实际运算中会有大量的负数,此时我们可以将(2^k)个k-bit数一分为二,一半表示整数,另一半表示负数。那么此时表示负数就有两种思路,第一种思路:以最高位bit代表符号,0表示正数,1表示负数,这种方法称为符号位表示法;第二种思路,这也正是早期计算机如CDC6600所采用,其方法是:将一个正数的所有bit全部取反,即得到该正数所对应的负数编码,例如,+5二进制表示为00101,那么-5的二进制表示则为11010,我们称之为反码表示法。

前面提到的两种编码方法,符号位法和反码法,在硬件逻辑设计上都相当复杂。因此,最终设计的更适合硬件操作的编码方案是补码表示法。其计算规则如下:

  • 原码:数字最原始的二进制表示法,最高位为符号位,0表示正数,1表示负数。
  • 反码:对于正数来说,原码=反码;对于负数来说,除符号位外的其他编码全部取反(即0变1,1变0)
  • 补码:对于正数来说,原码=反码=补码;对于负数来说,补码=反码+1

几乎所有的计算机都采用相同的实现机制完成加法运算,即算术逻辑运算单元(Arithmetic and Logic Unit,ALU)。它有两个输入和一个输出,它的功能就是将两个二进制数输入按位相加,并在输出端给出结果。例如,假设两个输入数为00110、00101,则计算过程如下:

        00110
        00101
        -----
        01011

二进制的加法过程和十进制的加法完全相同。从右向左将两数按列对齐并依次相加;如果前列的加法产生进位,则该进位bit参加其左边列的加法操作。

值得一提的是,ALU不知道也不关心它的两个输入数所代表的任何含义。换句话说,它只会对两个二进制数做加法(ADD)而不考虑其他(如正数、负数等因素)。这意味着我们必须为它选择一个合适的编码方式,以保证无论输入数是什么形式,它都将产生正确结果。所谓“进位对结果不产生影响”,可以理解为我们读ALU的输出结果时,只会去读那些有效位,而“最高位”所产生的进位,通常被用做控制(而不是运算)目的。例如:-1的补码为11111,而1的补码为00001,对-1和1进行相加后,结果为100000,此时最高位的1会被丢弃,即有效位为00000,即0。事实上,在补码运算中,进位bit始终是被忽略的。

例如:求数值-13的补码,首先求+13的补码为01101,则-13的原码为11101,它的反码为10010,它的补码为10011。

关于各个进制转换,在我之前的文章已经详细给出说明,若不懂,可以参考下面文章,链接如下:

数字系统与进制转换-@邂逅自己icon-default.png?t=N7T8https://blog.csdn.net/2302_76708905/article/details/140274373?spm=1001.2014.3001.5502

bit运算之一:算术运算

加法和减法

二进制补码的算术运算与我们常用的十进制算术运算非常相似,加法运算仍然是按位对齐,从右向左依次计算;所不同的是十进制是逢十进一(每位最大数是9),二进制是逢二进一(每位最大数是1)。减法可以理解为加上对应数字的相反数,A-B可以看做A+(-B)。

例如:计算11+3的值

        十进制数11的补码表示为    01011
        十进制数3的补码表示为     00011
        进行加法运算             ------
        两者的和为               01110

计算14-9的值

        十进制数14的补码表示为    01110
        十进制数-9的补码表示为    10111
        进行加法运算             ------
        两者的和为               00101
        转换为十进制得结果为      5

常用结论:一个数自己加自己就等于自己左移一位。如59的补码为00111011,它加上59结果为01110110。

符号扩展

在一些情况下,为了减少占用的空间,较小的数值会采用较少的bit来表示或存放。通常在一个数前面补0,并不会改变它的值。而在补码表示法中,正数前面加0并不会改变其值,负数前面加1并不会改变其值。我们称该操作位“符号扩展”(Sign=Extension),简称SEXT。符号扩展主要应用在两个不同长度的二进制相加时。

溢出

如果运算结果超出码值的最大值或最小值,会出现溢出问题。

在日常生活中,如汽车里程表在达到最高行驶里程后将会舍弃最高位,如:当前值为99992,而汽车又行驶100单位距离后,结果为00092。而对于有符号整数,要解决溢出问题就比较麻烦,幸运的是,其检测机制很容易实现。因为两个正数相加,其结果也必然是正数,而如果ALU给出的结果为负数,显然出错了。如 01001+01011=10100,显然是错的。同理,对于负数来说,两个负数的和必然也是负数,如果结果为正数,显然是出错了。事实上,也只有在这两种同符号运算情况下(即正数加正数、负数加负数),才会发生溢出。一个正数和一个负数相加,永远都不会溢出。

bit运算之二:逻辑运算(Logical Operation)

逻辑运算的操作对象是逻辑变量。逻辑变量的取值只有两个:0或1,这两个数也可以代表逻辑值中的“假”(false)和“真”(true)。

“与”运算

“与”(AND)是一个二元逻辑运算,这意味着它需要两个源操作数,且每个操作数的取值要么为0、要么为1。如果两个源操作数同时为1,则AND输出的结果为1,否则,结果皆为0。逻辑操作的功能(或行为)定义的常用描述方式是“真值表”(truth table)。真值表的行数和列数分别为(2^n和n+1),前n列分别代表n个源操作数。以两输入ADN单元为例,其真值表为:

ABAND
000
010
100
111

也可以对两个长度为m-bit的二进制数做AND运算,即将两个操作数按位对齐,然后对其中的每一对bit进行AND运算。

AND运算的示例如下:

操作数a:0011101001101001
操作数b:0101100100100001
        -----------------
AND结果:0001100000100001

假设有一个8-bit数A,其最低两位有特殊含义。如果计算机根据A的最低两位值做4种不同的操作,如何单独提取这两位的值?

可以采用“屏蔽字位”(bit mask)操作。“屏蔽字位”也是一个二进制数,我们可以将其理解为由两部分组成—即我们关心的位和我们忽略的位这两部分。本例中,屏蔽字位为00000011,它与其它操作数进行AND运算时,结果为:从7到2的最高6位必定为0,而结果的低2位与A原有的低两位完全相同。因此,屏蔽字位能够“屏蔽”掉从7到2的那些位。屏蔽字的作用,就是将我们所感兴趣的那些位提取出来。

“或”运算

“或”(OR)也是一个二元运算符,它的两个源操作数都是逻辑变量,取值为0或1。仅当两个源操作数都为0时,OR的输出结果才为0;其他情况下,OR输出都为1.换句话说,两个源操作数中任意一个为1,则OR结果必然为1。OR运算的真值表如下:

也可以对两个长度为m-bit的二进制数做OR运算,即将两个操作数按位对齐,然后对其中的每一对bit进行OR运算。

OR运算的示例如下:

操作数a:0011101001101001
操作数b:0101100100100001
        -----------------
OR结果: 0111101101101001

“非”运算

“非”(NOT)运算时一元逻辑运算,它只需要一个源操作数。其真值表如下:

ANOT
10
01

同理,也可以对m-bit的数进行按位NOT操作,操作示例如下:

操作数a:0011101001101001
        -----------------
NOT结果:1100010110010110

“异或”运算

“异或”(exclusive-OR,简称XOR),也是一个二元逻辑运算。它的两个源操作数都是逻辑变量,取值为0或1。如果两个输入值不同,则XOR输出结果为1;如果两者相同,则XOR输出为0。XOR真值表如下:

也可以对两个长度为m-bit的二进制数做XOR运算,即将两个操作数按位对齐,然后对其中的每一对bit进行XOR运算。

OR运算的示例如下:

操作数a:0011101001101001
操作数b:0101100100100001
        -----------------
XOR结果: 0110001101001000

如果要判断两个二进制数是否相同,可以通过XOR操作来完成。如果两个数完全相同,则他们之间XOR输出结果必然为0。

其他类型

除整数类型外,通常我们还会遇到如位矢量(bit vector)、浮点数(float-point)、ASCII码和十六进制(HEX)等数据类型。

位矢量(bit vector)

在很多复杂系统中,包含了许多独立单元,每个单元或忙或空闲。重要的是,我们必须从各个单元中判断并选取那些空闲的单元,以便我们为其分配任务。假设存在n个单元,我们可以用一个n-bit的二进制数代表这n个单元。当某个单元空闲时,我们将相应的单元清0,当某个单元忙碌时,我们将相应的单元置1.我们称这个二进制数为位矢量。

例如:假设要监视8台机器的运行状态,我们可以用一个8-bit矢量BUSYNESS来代表他们。其中每个bit代表一台机器,如果该机器忙,则对应位为0,若空闲则为1,每个bit的编号从右向左分别为0~7。不妨假设BUSYNESS=11000010,则表示第1、6、7号机器处于空闲状态,从而可以为他们分配任务。

假设我们将任务分配给了7号机器,则通过AND运算更新BUSYNESS矢量的bit7。AND运算的两个输入中,一个是当前矢量BUSYNESS,另一个是屏蔽字01111111。该屏蔽字的目的是在不影响其他位的情况下,清除BUSYNESS矢量的第7位。操作后的结果为BUSYNESS矢量变为01000010。

假设当前第5台机器完成任务,我们要更新BUSYNESS矢量的值,即将矢量中第5位置置1,则通过OR运算来完成,让BUSYNESS和屏蔽字00100000相OR,可将BUSYNESS变为01100010。

浮点数

在LC-3中,整数的表示方法是16-bit补码,其中15位表示它的数值(绝对值),最高的1位则用来代表该整数的符号。因此LC-3能表示的数值范围为-2^15~2^15-1(即-32768~32767),我们称LC-3的数值表示精度(precision)是15位,范围是2^15。但在很多情况下,我们要表示更大的数值,如6.023×10^23(摩尔常数),显然这个数超过了16-bit二进制数的表达范围。其实,更重要的是能够表达6023这个四位十进制数。

浮点数的引入可以解决这个问题。在浮点表示法中,除符号位外,并不是将所有bit都用于精度表示,而是一部分bit用于表示数值范围(多大、多小),另一部分用于表示数值精度。

大多数指令集都定义了一种或多种浮点数类型。其中之一通常被称为“float”类型,由32-bit组成,各bit定义如下:

  • 符号:1bit,代表符号(正数或负数)
  • 数值范围:8bit,代表范围(指数,exponent)
  • 数值精度:23bit,代表精度(尾数部分,fraction)

该格式也是IEEE浮点运算标准的一部分。

浮点数类型

注意:尾数部分是被正则化的,即小数点左边有且仅有一位非0数字,但二进制方式下,这个非0数字只可能是1,所以这个1可以被省略。因此,23bit就能表示24位的精度。注意,在浮点表示法中,fraction将被正则化,即小数点左边有且仅有一个非零数(十进制)。指数值00000000代表指数值为-126,且尾数中小数点左边默认数字是0(而不是1),因此,该浮点数的值为-1^s×0.尾数×2^(-126)。

对浮点数中指数字段的254个取值,解释如下:实际的指数值等于该无符号整数减127之后的结果。例如:如果实际指数值为+8,那么指数部分则表示为10000111(即无符号数135);如果实际指数值为-125,那么指数部分则表示为00000010(即无符号数2)。

最后一个字段为符号位,:0代表正数、1代表负数。公式中-1^s如果s=0,则结果为1,如果s=1则结果为-1。

例如:用IEEE浮点数表示-6的八分之五。

首先将-6的八分之五转换为二进制数-110.101,再将其正则化处理得到-1.10101×2^2;符号位为1,表示这是负数,指数部分为10000001,即无符号数125,代表实际指数为2;尾数部分为省略左边1之后的数,精度为23位,因此尾数部分为10101000000000000000000。因此,-6的八分之五的IEEE浮点数表示为:

1         10000001        10101000000000000000000

例如:问IEEE浮点数00111101100000000000000000000000代表什么数?

最左边为0,表示这是一个正数。随后的八位为无符号数123,将其减去127后得其实际指数为-4.最后23位全为0,所以它代表数值+1.0000000000000000000000×2^(-4),即十六分之一。

例如: 0        10000011        0010100000000000000000

指数字段内容为131,代表实际指数值为131-127=4,在小数点左边补1,并将尾数字段放在小数点右边得1.00101,再将小数点右移4位,得10010.1,即18.5。

例如: 1        10000010        0010100000000000000000

符号位1代表负数。指数字段为130,代表实际指数值为130-127=3,在尾数字段前小数点左边添1,得1.00101,再将小数点右移3位得1001.01,则结果为-9.25。

例如:0        11111110        11111111111111111111111

指数值等于254-127=+127,在尾数字段及其小数点左边补1,,得1.1111111111111111111111,即大约为2,因此结果约等于2^(128)。

例如: 1        00000000        0000000000000000000001

符号为1表示负数,指数字段全为0,表示指数值-126,此时小数点左边补0,尾数值为2^(-23),因此该浮点数为-2^(-23)×2^(-126),即2^(-149)。

浮点数,既可以表示非常大的数值,也可以表达非常小的数值,只是牺牲掉一些数值精度而已。

ASCII码

它是一种用于在计算机处理单元和输入/输出设备之间传递“字符”(character)的编码标准,这种8-bit编码方式被称为ASCII码。ASCII代表美国信息互换标准码(America Standard Code for Information Interchange),它的存在为计算机厂家、设备厂家(生产键盘、显示器等设备)之间提供了一个定义字符格式的共同标准。每次在键盘上敲键,都将产生唯一的ASCII码,即当用户在键盘上敲下一个按键时,键盘传输给计算机的是其ASCII码值。

键盘上的大多数按键,都对应不止一个ASCII码,如大写的E的ASCII码是01000101,而小写的e是01100101,但这两个字母在给键盘上却是同一个按键。键盘通过功能键shift是否同时按下来区别两种情况。另外,在显示器上输出的字符,也是由计算机通过ASCII编码方式传输给计算机的。

ASCII码 - 基本ASCII码和扩展ASCII码,中文最全ASCII码对照表0~255 (asciim.cn)icon-default.png?t=N7T8https://www.asciim.cn/最后文章创作不易,如果本文对大家有帮助的话,还请大家多多点赞加关注喔,谢谢大家!

  • 17
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值