跳至正文
View Categories

3 min read

相信大家在学习之余,也会参与或者观看一些体育比赛吧,毕竟大家都是德智体美全面发展的好学生。

无论是足球、篮球,还是其它的运动比赛,都有一样与编程非常相关的东西!那就是 — 记分牌!

那么,两者之间究竟有什么联系呢?

1. 十进制 #

大家可以回顾一下,记分牌的记分过程,是什么样子的呢?

我们的记分牌,可以记录超过 9 的数字吗?

如果,只有一位数字区域,那是不可以的。
由于,一个数字区域,只可以放一个数字(0-9),所以这时候,就需要两位数字区域了。

其实大家一看就知道了,这其实就是我们生活中常用的数字啊!
这有什么稀奇的呢?

其实,我们生活中,这种“满十进一”的计数方式,我们称之为“十进制”。

这种“满十进一”的机制我们都已经习以为常,所以都不觉得,这有什么神奇。

大家知道吗,其实人类历史上,还出现过不是“满十进一”的计数方式呢。

  • 12 进制的计数法:中国古代的地支(代表一天的时间,12个时辰)“子、丑、寅、卯、辰、巳、午、未、申、酉、戌、亥”
  • 12 进制的计数法:中国的十二生肖“鼠、牛、虎、兔、龙、蛇、马、羊、猴、鸡、狗、猪”;(十二生肖与十二地支一一对应)

中国古代也有一种十进制的计数法:“甲、乙、丙、丁、戊、己、庚、辛、壬、癸”;(天干)

聪明的古人将“十天干”和“十二地支”结合起来,形成了独特的干支纪年法,我们常常会在历史中看到这种纪年法,例如:辛亥革命、戊戌变法、甲午战争。

干支纪年法:
甲子、乙丑、丙寅、丁卯、戊辰、己巳、庚午、辛未、壬申、癸酉、
甲戌、乙亥、丙子、丁丑、戊寅、己卯、庚辰、辛巳、壬午、癸未、
甲申、乙酉、丙戌、丁亥、戊子、己丑、庚寅、辛卯、壬辰、癸巳、
甲午、乙未、丙申、丁酉、戊戌、己亥、庚子、辛丑、壬寅、癸卯、
甲辰、乙巳、丙午、丁未、戊申、己酉、庚戌、辛亥、壬子、癸丑、
甲寅、乙卯、丙辰、丁巳、戊午、己未、庚申、辛酉、壬戌、癸亥

细心的同学可能发现了用干支纪年法60年为一循环,而不是120年(十天干和十二地支有10*12=120种组合方式)
这是因为每过一年,天干和地支要同时加1,而不是像十进制数学中满十才进一,所以最后可能的只有60种组合方式。

思考:

2024年用干支纪年法表示是甲辰年,那么大家出生那年用干支纪年法该怎么表示呢?

2. 二进制 #

我们生活中,常用阿拉伯数组,就是十进制。数学中其实还有其他几种进制,我们先来看一下,“二进制”

从上面的动图可以看出来,其实“二进制”,就是“满二进一”

或许大家都听说过,“二进制”和计算机是关系非常紧密的。
现在大家已经学习过来 C++ 的一些知识,那么,在下一个章节中,我们将给大家介绍,它们之间的联系。

不过这会儿,我们还有一个很重要的知识要学习,那就是“进制转换”
由于进制很多,不可能一一去讲。我们只需掌握重要的几种就可以了。

2.1 二进制和十进制转换 #

我们先来看一下,十进制数中,我们有这样的约定:

千    百    十    个
1     2     3    4

这是我们学习过的“数位”
那么,给定一个数(比如 1234),如何计算它的值呢?

从个位开始:
个: 4         = 4
十: 3 * 10    = 30
百: 2 * 100   = 200
千: 1 * 1000  = 1000

所以,总和为:1000 + 200 + 30 * 4 = 1234

其实这个方法,可以将任意的进制,转化成“十进制”。在上一讲中,我们其实已经使用过这个方法了。

现在我们来看一下,二进制该怎么转化。

2.1.1 二进制 to 十进制 #

假设有一个二进制数,如何转化成十进制数呢?我们先来看几个例子:

0000   // 0 (可以先数一数,来得到对应的十进制数)
0001   // 1
0010   // 2
0100   // 4
1000   // 8

然后我们可以这样约定,在二进制数中:

(2^3)  (2^2)  (2^1)  (2^0)  
 1      0      1      0

然后,给定一个数(比如 1010),如何计算它的十进制值呢?

从个位开始:
个: 0 * 2^0  = 0
二: 1 * 2^1  = 2
四: 0 * 2^2  = 0
八: 1 * 2^3  = 8

所以,总和为:8 + 0 + 2 + 0 = 10

请计算下面几个二进制数的十进制值是多少。
注意,请写出计算过程。

1111
111
11
1011 0101 // 二进制数的写法上,我们习惯上,书写时,4 位一组
0110 0010

答案:

15
7
3
181
98

以下这几个,希望大家能够记住。

0000   // 0
0001   // 1
0010   // 2
0100   // 4
1000   // 8

2.1.2 十进制 to 二进制 #

需要使用“短除法”
假设有一个十进制数:125

   
2|125     
  ▔▔▔▔
 2|62           1     // 商 62 ,余数 1
   ▔▔▔▔
  2|31          0     // 商 31 ,余数 0
    ▔▔▔▔
   2|15         1     // 商 15 ,余数 1
     ▔▔▔▔
    2|7         1     // 商 7 ,余数 1
      ▔▔▔▔
     2|3        1     // 商 3 ,余数 1
       ▔▔▔▔
        1        1     // 商 1 ,余数 1
   
不能再除。

先写最后一步的“商”
然后,倒着将所有余数写出来。(先写最底下的余数)

1111 1101

这个方法,请多加练习。

3. 十六进制 #

一样的道理,阿拉伯数字只有 0-9,不够用来表示 16 个数字。
但是,对于“十六进制”,在我们编程中是非常重要的一种计数方式,所以专门约定,使用 ABCDEF 来补充
我们一起来数一数吧。

0
1
2
3
4
5
6
7
8
9
A // 10
B // 11
C // 12
D // 13
E // 14
F // 15

10
11
12
13
14
15
16
17
18
19
1A
1B
1C
1D
1E
1F

20
21
22
23
24
25
26
27
28
29
2A
2B
2C
2D
2E
2F
...

3.1 十六进制和十进制转换 #

3.1.1 十六进制 to 十进制 #

首先,还是在,十进制数中,我们有这样的约定:

千    百    十    个
1     2     3    4

现在我们来看一下,十六进制该怎么转化。
假设有一个十六进制,

5AF1 

然后我们可以这样约定,在十六进制中:

(16^3)    (16^2)    (16^1)    (16^0)
5          A         F        1

如何计算它的十进制值呢?

从个位开始:
(16^0): 1 * (16^0) = 1 * 1 = 1
(16^1): F * (16^1) = 15 * 16 = 240
(16^2): A * (16^2) = 10 * 16*16 = 2560
(16^3): 5 * (16^3) = 5  * 16*16*16 = 20480

所以,总和为:20480 + 2560 + 240 + 1 = 23281

请计算下面几个十六进制数的十进制值是多少。
注意,请写出计算过程。

FFFF
FF00
10
100
1000
ABCD

答案:

65535
255
16
256
4096
43981

3.1.2 十进制 to 十六进制 #

需要使用“短除法”
假设有一个十进制数:23281

16|23281     
   ▔▔▔▔▔
 16|1455        1     // 商 1455 ,余数 1
    ▔▔▔▔▔
  16|90         F     // 商 90 ,余数 15(F)
     ▔▔▔▔▔
      5          A     // 商 5 ,余数 10(A)
    
不能再除。

先写最后一步的“商”
然后,倒着将所有余数写出来。(先写最底下的余数)

5AF1

这个方法,请多加练习。

3.2 十六进制和二进制转换 #

二进制对于编程来说,是非常重要的。虽然我们还没有具体介绍原因,但是已经无数次的再强调了。

不过,二进制有一个显而易见的缺点,那就是太太太长。。。

1000      // 十进制 8
1111 1111 // 十进制 255
0100 1001 1001 0110 0000 0010 1101 0010 // 十进制 1234567890

但是二进制太重要了,我们不能不使用它。所以,我们为了表示方便,就经常使用十六进制。

原因也是非常显而易见的,我们这儿,举几个例子,大家以看就明白了。

0001                 // 十六进制 1
0010                 // 十六进制 2
0100                 // 十六进制 4
1000                 // 十六进制 8
1111                 // 十六进制 F
1111 1111            // 十六进制 FF
1111 1111 0000 0001  // 十六进制 FF01

因为二进制对程序而言非常重要,而十六进制沾了二进制的光,所以在编程中,也应用广泛。

4 位二进制,正好对应 1 位十六进制

二进制          十六进制
0000              0
0001              1
0010              2
0011              3
0100              4
0101              5
0110              6
0111              7
1000              8
1001              9
1010              A
1011              B
1100              C
1101              D
1110              E
1111              F

注意:

二进制转换十六进制时,要从右往左每四位一组,如果最左边一组不满四位,在开头补0补齐四位

10100100110

0101 0010 0110 // 正确

1010 0100 110  // 错误

这是非常重要的,要记得非常牢。

4. 八进制 #

“八进制”,就是“满八进一”

0
1
2
3
4
5
6
7
10
11
12
13
14
15
16
17
20
21
...

4.1 八进制和十进制转换 #

八进制和十进制之间的转换可以参照前面二进制、十六进制和十进制的转换,这里不再赘述。

我们通过几个练习来学习一下

31(十进制)    ==>   ?(八进制)
100(十进制)   ==>   ?(八进制)
1107(十进制)  ==>   ?(八进制)

31(八进制)    ==>   ?(十进制)
100(八进制)   ==>   ?(十进制)
1107(八进制)  ==>   ?(十进制)

4.2 八进制和二进制转换 #

八进制转二进制与十六进制转二进制类似。

3位二进制,正好对应 1 位八进制

100            // 八进制 4
111 101        // 八进制 75(从右往左每三位一组)
100 000 011    // 八进制 403
二进制          八进制
000              0
001              1
010              2
011              3
100              4
101              5
110              6
111              7

5. 二进制、八进制、十六进制在 C++ 中的写法 #

虽然我们一直说,二进制很重要,但是

  • C++ 中,没有二进制数的直接表示方法!!!
  • 二进制数,是通过十六进制数,表示的!

请看代码:

int a;
a = 0xFF01;  // 将 a 赋值为 0xFF01,这是十六进制数
a = 0x1;     // 以 0x 开始,表示为十六进制
a = 0x0011;  // 可以以 0 开头

a = 23281;   // 将 a 赋值为 23281,这是十进制数

a = o1;      // 将 a 赋值为 01,这是八进制数
a = o452;    // 以 o 开始,表示为八进制。注意,这是字母 o,不是数字 0
a = o77;
  • 0x 是十六进制数的开头。x 也可以大写,一般习惯小习。
  • o 是八进制数的开头。注意,这不是数字0,这是字母o,也可以大写。
  • C++ 中,十六进制的负数,非常特殊。不可以写作 -0xFF ,要使用反码,我们将在后面的课程中介绍。

请练习一下,完成下面转化。注意书写计算过程。

1111(2进制)  ==>   0x????
1100(2进制)  ==>   0x????

1111 1100(2进制)  ==>   0x????
1001 1101(2进制)  ==>   0x????

0x0077  ==> ????(2进制)
0x00e8  ==> ????(2进制)      // C++ 的十六进制写法中,不区分字母的大小写
0x7a5d  ==> ????(2进制)