相信大家在学习之余,也会参与或者观看一些体育比赛吧,毕竟大家都是德智体美全面发展的好学生。
无论是足球、篮球,还是其它的运动比赛,都有一样与编程非常相关的东西!那就是 — 记分牌!
那么,两者之间究竟有什么联系呢?
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进制)