跳转到内容

C++ 编程/学习基础

来自维基教科书,为开放世界提供开放书籍
Clipboard

待办事项
在完成出色的清理工作后,此页面应该被挖掘出可用于C++ 编程/编程语言/C++/代码/语句/变量的内容,并合并到计算机编程维基教科书中,而无需进行任何修改。


二进制数系统

[编辑 | 编辑源代码]

大多数计算机系统使用二进制逻辑运行。计算机使用两个电压电平表示值,通常是 0V 表示逻辑 0,而 +3.3V 或 +5V 表示逻辑 1。这两个电压电平恰好表示两个不同的值,按照惯例,这些值是。巧合的是,这两个值对应于二进制数系统使用的两个数字。由于计算机使用的逻辑电平与二进制数系统使用的两个数字之间存在对应关系,因此计算机采用二进制系统也就不足为奇了。

二进制数格式

[编辑 | 编辑源代码]

二进制数系统使用基数 2,它只包含数字01

在美国和其他国家,每三位十进制数字用逗号分隔,使较大的数字更容易阅读。例如,123,456,789 比 123456789 更容易阅读。我们对二进制数也采用了类似的约定。为了使二进制数更易读,我们在小数点左侧的最低有效数字开始,每四位数字添加一个空格。例如,二进制值 1010111110110010 将写成1010 1111 1011 0010

使用上面的示例1010 1111 1011 0010

  • 最右侧的序列(0010)位于位号 0,其值为0。位号 0 称为最低有效位,或lsb
  • 左侧的每个位都分配了下一个连续的位号。位 1位 2等等...
  • 最左侧的位(1010)通常称为最高有效位,或msb,其值为1

我们通常将二进制数写成一系列位。不同位的大小有定义的边界

名称 大小(位) 示例
1 1
字节 4 0101
字节 8 0000 0101
16 0000 0000 0000 0101
双字 32 0000 0000 0000 0000 0000 0000 0000 0101

在任何进制中,我们可以添加任意数量的领先零而不会改变其值,但在二进制数系统中,添加领先零会将位调整到所需的大小。例如,我们可以将数字5表示为一个

位 101;

字节 0101;

字节 0000 0101;

字 0000 0000 0000 0101; 或

双字 0000 0000 0000 0000 0000 0000 0000 0101

关于名称的说明

[编辑 | 编辑源代码]

字的边界可以定义为 16 位或处理器的地址总线大小。因此,字和双字不是固定大小,而是根据系统(具体取决于处理器)而有所不同。

对于 8085 和 8086 微处理器,字是一组 16 位。我们从位号 0 (b0) 到十五 (b15) 对字中的位进行编号,如下所示

b15 b14 b13 b12 b11 b10 b9 b8 b7 b6 b5 b4 b3 b2 b1 b0

请记住,b0LSBb15msb,在引用字中的其他位时,请使用它们的位号。请注意,字正好包含两个字节。b0-b7构成低字节,b8-b15构成高字节。自然,字可以进一步细分为四个字节。字节零是低字节(b0-b4),字节三是字的高字节(b12-b15)。另外两个字节是“字节一”和“字节二”。

使用 16 位,你可以表示2^1665,536个不同的值。这些值可能是范围为 0 => 65,535 的无符号数值、范围为 -32,768 => +32,767 的有符号数值,或任何不超过65,536个值的任何其他数据类型。字的三种主要用途是

  • 16 位整型数据值
  • 16 位内存地址
  • 任何需要 16 位或更少位的进制
双字

双字就是两个字,所以双字量是 32 位。自然,这个双字可以细分为一个高字和一个低字,四个字节或八个字节。

双字可以表示各种不同的数据

  • 范围为 0 => 4,294,967,295 的无符号双字
  • 范围为 - 2,147,483,648 => +2,147,483,647 的有符号双字
  • 32 位浮点数
  • 任何需要 32 位或更少位的数据

进制转换

[编辑 | 编辑源代码]

二进制转十进制

[编辑 | 编辑源代码]

从二进制数转换为十进制数非常容易。

例如,让我们分解二进制值1100 1010

数字 1 1 0 0 1 0 1 0
位号 b7 b6 b5 b4 b3 b2 b1 b0
基数 2 2^7 2^6 2^5 2^4 2^3 2^2 2^1 2^0

现在就像十进制系统一样,我们将每个数字乘以基数 2及其加权位置值,然后求和,如下所示

1(2^7) 1(128) 128
1(2^6) 1(64) 64
0(2^5) 0(32) 0
0(2^4) 0(16) 0
1(2^3) 1(8) 8
0(2^2) 0(4) 0
1(2^1) 1(2) 2
0(2^0) 0(1) 0
=202

十进制转二进制

[编辑 | 编辑源代码]

从十进制转换为二进制稍微困难一些。

有两种方法,除以 2减去加权位置值

除法方法
[编辑 | 编辑源代码]

为此,我们将十进制数除以 2,如果余数是0,则写下0。如果余数是1,则写下1。重复此过程,直到商为0

余数将表示十进制数的二进制等效值。余数值从最低有效数字写入最高有效数字。因此,每个新的余数值都写在之前的余数值左侧

例如,考虑数字2671

除法 余数 二进制数
2671 / 2 1335 1 1
1335 / 2 667 1 11
667 / 2 333 1 111
333 / 2 166 1 1111
166 / 2 83 0 0 1111
83 / 2 41 1 10 1111
41 / 2 20 1 110 1111
20 / 2 10 0 0110 1111
10 / 2 5 0 0 0110 1111
5 / 2 2 1 10 0110 1111
2 / 2 1 0 010 0110 1111
1 / 2 0 1 1010 0110 1111
减法方法
[编辑 | 编辑源代码]

从一个大于该数字的加权位置值开始。如果该数字小于加权值,则写下0并减去0。如果该数字大于加权值,则写下1,但要减去加权值。重复此过程,直到结果为0

在执行减法时,数字将表示从最高有效位到最低有效位的十进制数的二进制等效值。因此,每个新数字都写到前一个数字的右边

考虑相同的数字,2671

加权值 减法 余数 二进制数
2^12 = 4096 2671 - 0 2671 0
2^11 = 2048 2671 -2048 623 01
2^10 = 1024 623 - 0 623 010
2^9 = 512 623 - 512 111 0101
2^8 = 256 111 - 0 111 0 1010
2^7 = 128 111 - 0 111 01 0100
2^6 = 64 111 - 64 47 0 1010 01
2^5 = 32 47 - 32 15 0 1010 011
2^4 = 16 15 - 0 15 0 1010 0110
2^3 = 8 15 - 8 7 0 1010 0110 1
2^2 = 4 7 - 4 3 0 1010 0110 11
2^1 = 2 3 - 2 1 0 1010 0110 111
2^0 = 1 1 - 1 0 0 1010 0110 1111

八进制数系

[编辑 | 编辑源代码]

虽然这曾经是一个流行的数制,特别是在数字设备公司 PDP/8 和其他旧的计算机系统中,但如今很少使用。八进制系统基于二进制系统,以 3 位为界。

八进制系统使用基数 8,它只包含数字 0,1,2,3,4,5,6 和 7(任何其他数字都会使数字成为无效的八进制数)。

八进制数字的二进制形式
八进制数字 二进制数
0 000
1 001
2 010
3 011
4 100
5 101
6 110
7 111
现在是每个八进制位置的加权值
8^6 8^5 8^4 8^3 8^2 8^1 8^0
262144 32768 4096 512 64 8 1

二进制转换为八进制

[编辑 | 编辑源代码]

将二进制值转换为八进制数很容易。

首先,将二进制数从LSBMSB分成 3 位的节,然后将 3 位的二进制数转换为它的八进制等效值。

让我们分解二进制值1010111110110010

3 位 001 010 111 110 110 010
MSB LSB
八进制数字 1 2 7 6 6 2

八进制转换为二进制

[编辑 | 编辑源代码]

从八进制数转换为二进制值也很容易。

将十进制数转换为它的 3 位二进制等效值,然后合并 3 位的节。

让我们以上面的八进制数127662为例,将其分解

八进制数字 3 位
1 001
2 010
7 111
6 110
6 110
2 010

这将产生二进制数001010111110110010,或者以更易读的格式表示为0000 1010 1111 1011 0010

八进制转换为十进制

[编辑 | 编辑源代码]

要将八进制转换为十进制,请将每个位置的值乘以其八进制权重,然后将每个值加起来。

同样,让我们以八进制值127662为例

1(8^5) 1(32768) 32768
2(8^4) 2(4096) 8192
7(8^3) 7(512) 3584
6(8^2) 6(64) 384
6(8^1) 6(8) 48
2(8^0) 2(1) 2
=44978

十进制转换为八进制

[编辑 | 编辑源代码]

将十进制转换为八进制稍微困难一些。

将十进制转换为八进制的典型方法是重复除以 8。对于此方法,将十进制数除以 8,并将余数写在旁边作为最低有效位。通过将商除以 8 并写入余数,直到商为 0,继续此过程。在执行除法时,将表示十进制数的八进制等效值的余数从最低有效位(右边)开始写入,并将每个新数字写入到前一个数字的下一个更高有效位(左边)。考虑数字 44978。

除法 余数 八进制数
44978 / 8 5622 2 2
5622 / 8 702 6 62
702 / 8 87 6 662
87 / 8 10 7 7662
10 / 8 1 2 27662
1 / 8 0 1 127662

如您所见,我们又回到了原来的数字。

十六进制数系

[编辑 | 编辑源代码]

二进制系统的一个大问题是冗长。例如,表示值 202 需要 8 个二进制数字,而十进制版本只需要 3 个十进制数字。特别是对于较大的值,二进制数变得过于笨拙。十六进制记数系统解决了这些问题。

十六进制数非常紧凑,并且易于从十六进制转换为二进制,以及从二进制转换为十六进制。由于我们经常需要将十六进制数输入计算机系统,因此我们需要一种不同的机制来表示十六进制数,因为您无法输入下标来表示相关值的基数。

十六进制系统基于二进制系统,使用一个字节或 4 位为界。在汇编语言编程中,大多数汇编器要求十六进制数的第一个数字为0,并且我们在数字末尾放置一个H来表示数字基数。

十六进制数系使用基数 16,它只包含数字09以及字母A、B、C、D、EF

此表提供了从 0 到 16 的十进制值的所有信息,您可以将其用于将一种数制转换为任何其他数制。

十进制 十六进制 二进制 八进制
00 00H 0000 00Q
01 01H 0001 01Q
02 02H 0010 02Q
03 03H 0011 03Q
04 04H 0100 04Q
05 05H 0101 05Q
06 06H 0110 06Q
07 07H 0111 07Q
08 08H 1000 10Q
09 09H 1001 11Q
10 0AH 1010 12Q
11 0BH 1011 13Q
12 0CH 1100 14Q
13 0DH 1101 15Q
14 0EH 1110 16Q
15 0FH 1111 17Q
16 10H 1 0000 20Q

十六进制转换为二进制

[编辑 | 编辑源代码]

要将十六进制数转换为二进制数

1. 将十六进制数分解为每个单独的十六进制数字

2. 替换每个十六进制数字对应的二进制值

3. 每个二进制值从MSB(左边)开始到LSB(右边)写入

例如,要将0ABCDH转换为二进制值,只需根据上面的表格转换每个十六进制数字。

十六进制数字 二进制值
0 0000
A 1010
B 1011
C 1100
D 1101
0ABCDH = 0000 1010 1011 1100 1101

二进制转换为十六进制

[编辑 | 编辑源代码]

将二进制数转换为十六进制格式几乎同样容易。

例如,给定二进制数1011001010,第一步是在MSB位置添加两个零,使其包含 12 位。然后将二进制值分成 4 位一组,因此修改后的二进制值变为0010 1100 1010。然后我们在上面的表格中查找二进制值并替换相应的十六进制数字

0010 2
1100 C
1010 A

因此0010 1100 1010 = 2CA

另一个例子,1010111110110010 转换为 AFB2

十六进制转换为十进制转换

[编辑 | 编辑源代码]

每个位置的加权值如下所示

16^0 1
16^1 16
16^2 256
16^3 4096

要将十六进制转换为十进制,请将每个位置的值乘以其加权值,然后加起来。使用上面的表格和前面的例子,0AFB2H,我们预计将获得十进制值44978

A(16^3) 10(4096) 40960
F(16^2) 15(256) 3840
B(16^1) 11(16) 176
2(16^0) 2(1) 2
=44978

十进制转换为十六进制

[编辑 | 编辑源代码]

将十进制转换为十六进制稍微困难一些。典型方法是重复除以 16

虽然我们也可以使用重复减去加权位置值,但这对于较大的十进制数而言更困难。

除法方法

将十进制数除以 16,并将余数写在旁边作为最低有效位。继续此过程,直到商为0。在执行除法时,将表示十进制数的十六进制等效值的余数从最低有效位(右边)开始写入,并将每个新数字写入到前一个数字的下一个更高有效位(左边)。考虑数字 44978。

除法 余数 十六进制数
44978 / 16 2811 2 2
2811 / 16 175 11 B2
175 / 16 10 15 FB2
10 / 16 0 10 0AFB2
44978 = 0AFB2

在 8085 程序中使用十六进制数时,汇编器通常要求最高有效位十六进制数字为 0,即使此数字位数超过寄存器的大小。这是汇编器要求,您的值将被正确地汇编。

十六进制加法

[编辑 | 编辑源代码]

像十进制数一样加法,但:

如果单个数字是 A 到 F,我们必须将其转换为十进制等效值(上面的表格中的值),然后加起来。

例如

求 D + C 的和

0DH = 13 以及 0CH = 12 所以;

13 + 12 = 25 因此;

D + C = 25 但是;

如果和大于或等于 16,我们将和替换为和减 16 并进位 1。

例如

25 - 16 = 9;然后

D + C = 19;最后

3) 如果和介于 10 到 15(十进制)之间,我们将用等效的十六进制数字替换和,例如

进位 --> 1 1
DF6D
+ 246C
溢出 --> 1 03D9

二进制和十六进制加法的更多示例:

进位 --> 11111
111011
+ 100111
溢出 --> 1 100010
进位 --> 1 1
11001
+ 01101
溢出 --> 1 00110
1235
+ 567A
无溢出 --> 68AF
进位 --> 111
A9876
+ FDCA0
溢出 --> 1 A7516

不同数制之间的转换

[编辑 | 编辑源代码]

位置数制

[编辑 | 编辑源代码]

我们的十进制数制被称为位置数制,因为数字的值取决于数字的位置。例如,数字 123 与 321 不同,即使使用了相同的数字。其他古代数制使用额外的符号来表示更大的值,但在位置数制中,每个数字的值由它在整个数字中的位置决定。最低位值是右边的位置,每个连续的左边的位置具有更高的位值。最右边的位置代表“个位”列,下一个位置代表“十位”列,下一个位置代表“百位”等。因此,数字 123 代表 1 个百和 2 个十和 3 个一,而数字 321 代表 3 个百和 2 个十和 1 个一。

每个位置的值对应于数制基数的幂。因此,对于我们的十进制数制,它使用基数 10,位值对应于 10 的幂

10^0 = 1
10^1 = 10
10^2 = 100
10^3 = 1000

从其他进制转换到十进制

[编辑 | 编辑源代码]

其他数制使用不同的基数。二进制数制使用基数 2,因此二进制数字的数字的位值对应于 2 的幂。

例如,二进制数 10011 的值是通过计算 该数字的每个二进制位 的位值来确定的

1 0 0 1 1 二进制数
(2^4) (2^3) (2^2) (2^1) (2^0) 位值

因此,二进制数 10011 代表值

1 (2^4) + 0(2^3) + 0 (2^2) + 1 (2^1) +1 ( 2^0)
= 16 + 0 + 0 + 2 + 1
= 19

相同的原理适用于任何进制。例如,数字 2132(以 5 为基) 对应于

2 1 3 2 以 5 为基的数字
(5^3) (5^2) (5^1) (5^0 位值

因此,数字 2132(以 5 为基) 的值是

2(5^3) +1(5^2) +3(5^1) +2(5^0)
=2(125) +1(25) +3(5) +2(1)
= 250 +25 +15 +2
= 292

从十进制转换到其他进制

[编辑 | 编辑源代码]

为了将十进制数转换为不同的进制,我们必须能够用其他进制的幂来表示该数字。要将十进制数 100 转换为 4 进制,我们必须弄清楚如何将 100 表示为 4 的幂之和,例如

100= 1(64) + 2(16) + 1(4) + 0(1)
= 1(4^3) + 2(4^2) + 1(4^1) + 0(4^0)

然后我们使用 4 的幂的系数来形成以 4 进制表示的数字

100 = 1 2 1 0 4 进制

另一种方法是重复地将十进制数除以要转换到的进制,直到商为零。当数字被除时,余数 - 反向顺序 - 形成数字在其他进制中的数字。例如

将十进制数 82 转换为 6 进制

82/6 = 13 余数 4
13/6 = 2 余数 1
2/6 = 0 余数 2

答案是通过反向顺序取余数 形成的:2 1 4(以 6 为基)

数制之间的转换示例

十进制 二进制 十六进制
255 1111 1111 FF
93 0101 1101 5D

定长二进制数

[编辑 | 编辑源代码]

计算机算术是在存储在定长内存位置中的数据上执行的,通常为 8 位、16 位或 32 位。

操作定长数字会遇到特殊问题。数字 280(以 10 为基)大于最大 8 位数;这会导致二进制表示中超过 8 位的进位,以及十六进制表示中超过两位的进位。在使用定长数字进行算术运算时,这些进位可能会丢失。

十进制 二进制 十六进制
201 11001001 C9
+79 +01001111 +4F
280 1 00011000 1 18

符号位- 使用一位表示符号,7 位表示数字。

示例:-1(在 8 位系统中)可以是 1000 0001(以 2 为基)

补码(在计算中最常使用)

示例:表示 -1(在 8 位系统中)的补码数字为 1111 1111(以 2 为基)

考虑自行车上的里程表数字:考虑自行车上的里程表数字

十进制示例里程表数字可用于带符号数字的加法和减法(补码)。- 2 + 998 + 3 + 003 + 1 1 001

在第二个示例中,正确的结果只是 +001;溢出在定长补码算术中被忽略。使用补码将减法视为加法,即 A - B = A + (-B) 重要提示:计算 -B 并相加比直接减法更容易。示例:- 005 + 995 + 003 + 997 + 008 1 992

请注意,995 和 997 以正常方式相加,溢出被忽略,结果为 992,它可以从补码(或里程表)系统转换回 -8,即正确答案。

signed   3-bit complement
    +3   003
    +2   002
    +1   001
     0   000
    -1   999
    -2   998
    -3   997
    -4   996
    -5   995
    -6   994
    -7   993
    -8   992

十进制 补码 二进制

  +127   01111111
  +126   01111110
  +125   01111101
   ...   ........
    +2   00000010
    +1   00000001
     0   00000000
    -1   11111111
    -2   11111110
   ...   ........
  -127   10000001
  -128   10000000

在 8 位定长补码数制中,有 256 个数字。为什么这些数字被称为补码?M - N = M + (-N),其中 -N 是 N 的补码。

示例:十进制

   + 1   =     00000001
   - 1   =   + 11111111
     0   =   1 00000000

它不等于 2^8 或 256;忽略溢出,正确答案为零。现在我们需要一种简单的方法来执行补码运算。

示例:-27(以 10 为基)在补码 8 位表示法中的表示是什么?

 2^8 - 1     11111111

- 27 - 00011011

             11100100   corresponds to flipping all the bits;
                        also known as 1's complement
   add 1   + 00000001
  result     11100101   -27 in 2's complement representation

这种方法是必要的,因为:1. 计算机中存储的数字的定长特性 2. 实现快速加法器比实现加法器和减法器更有效率 ________________________________________ 补码数字运算示例 补码形式的加法和减法 • 加法:要计算 N1 + N2,将 N1 加到 N2 • 减法:要计算 N1 - N2,将 N1 加到 -N2 示例:十进制 二进制 十六进制

   11   =     00001011   =     000B
 + 21   =   + 00010101   =   + 0015
   32   =     00100000   =     0020
   21   =     00010101   =     0015
 - 11   =   + 11110101   =   + FFF5
   10   =     00001010   =     000A
   11   =     00001011   =     000B
 - 21   =   + 11101011   =   + FFEB
 - 10   =     11110110   =     FFF6
 - 11   =     11110101   =     FFF5
 - 21   =   + 11101011   =   + FFEB
 - 32   =   1 11100000   =     FFE0

我们如何得到 -11 和 -21 的补码

11     00001011

~11 - 11110100 1 的补码 + 1 + 00000001 加 1 -11 11110101 补码表示

算法 1. 存储 N。2. 获取 ~N,即 N 的 1 的补码,方法是在数字的二进制表示中(逐位)将每个 0 替换为 1,反之亦然。3. 加 1 并忽略第八位后的任何进位。注意:此算法在十六进制中有效,方法是将每个数字 x 替换为其十六进制补码,即 15 - x。示例:11 的十六进制等效值为 $000B;然后其十六进制补码为 $FFF4,其中每个数字都计算为 $F - x。将 $FFF4 加 1 会得到 $FFF5,即 11 的补码。(在数字前面使用美元符号 ($) 表示它是 16 进制。)示例:在二进制中

N     0000 0110 0100 0111

~N - 1111 1001 1011 1000 1 的补码 +1 + 0000 0000 0000 0001 加 1 -N 1111 1001 1011 1001 补码表示

在十六进制中

N     0647

~N - F9B8 1 的补码 +1 + 0001 加 1 -N F9B9 补码表示

计算器将始终直接为您提供补码。最高有效位 (MSB) 是对应于 2 的最大幂的二进制位,对于负补码数字,它始终为 1。因此,它通常被称为符号位。在补码中,-0 = +0。从技术上讲,0 是其自身的补码。

N     00000000

~N - 11111111 1 的补码 +1 + 00000001 加 1 -N 00000000 补码表示

________________________________________ 定长算术问题 溢出和下溢 对于 16 位定长数制,

添加带符号数字很容易超过这些限制。第一位

      0011   $3000
      0110   $6000
      1001   $9000

此结果,来自在数制中添加两个正数,结果为 $9000,它大于 $7FFF,即允许的最大正数。实际上,$9000 等于 1001 0000 0000 0000,它是一个负数。结果的符号与操作数的符号不同。规则:如果在添加两个正补码数字时发生符号变化,则发生了溢出。我们可以将这些规则推广到带符号的加法和减法。

符号扩展 如果数字的长度不同怎么办?十进制 补码 二进制

         3-bit 4-bit  8-bit
    +3   011   0011   00000011
    +2   010   0010   00000010
    +1   001   0001   00000001
     0   000   0000   00000000
    -1   111   1111   11111111
    -2   110   1110   11111110
    -3   101   1101   11111101
    -4   100   1100   11111100

要将补码数字扩展到更多的二进制位,您只需将符号位向左继续扩展。示例:将 $9B 扩展到 16 位。$9B = 1001 1011 = 1111 1111 1001 1011 = $FF9B

将 $5F 扩展到 16 位。$5F = 0101 1111 = 0000 0000 0101 1111 = $005F

添加两个不同长度的补码数字 43A0 43A0

 9B     FF9B   need to sign extend; you can't just add zeros.

???? 1 433B

请注意,8 位 $9B 和 16 位 $FF9B 在各自的数制中都表示 -101。

华夏公益教科书