课程首页 › 第1部分 › 第12课

第12课 小数字大学问

第1部分 初识 C++ · 顺序结构· 知识点:进制

小数字大学问(进制)

加法中有进位,那是一种计数方法,我们把这种带有进位的计数方法称为“进制”。

插图

脑洞大开

想一想我们身边都有哪些进制?

十进制是我们最常用的进制。看看我们的手指,十进制的发明跟我们人类有10个手指有关。小时候,我们也习惯用手指来帮助计数。

还有六十进制,时间的表示中广泛使用了六十进制,一小时=60分钟,一分钟=60秒,60秒进位1分钟,60分钟进位1小时。

还有二十四进制,24小时就是一天;十二进制,12个月就是一年;等等。开动脑筋想想还有什么进制?

插图
插图

提出思考

既然人类习惯使用十进制,那为什么发明的计算机要使用二进制呢?

插图

提问是发明创造的开始。当初首先想到的应该是十进制,那用什么方式来表示不同的数字呢?

计算机是需要用电的,因此想到了电压,不通电时的电压0伏特表示数字0,通电后的电压1伏特表示1,2伏特表示2……10伏特表示10。看上去特别棒,但是电器件在使用过程可能会老化,同时外部环境也可能导致电压不是那么标准。当电压出现了2.5伏特时,到底表示的是2还是3呢?

插图

再思考一下,拉开数字之间的电压差距之后会怎样呢?假设将10伏特算作1,以10伏特为中心电压差距正负10内也都算作1,也就是0~20伏特的电压范围都算作1,那么这样来表示数字9,估计电压快要到200伏特了。

那有没有更好的办法呢?当然有,二进制由此诞生,只需要通电和不通电就可以解决,有电压表示1,没电压表示0,从此不需要那么纠结了。

插图

进制转换

插图

运行程序,输入:

输出结果为:

八进制:21

十进制:17

十六进制:11

(1)printf("八进制:%o\n十进制:%d\n十六进制:%x",num,num,num):将输入的十进制数字按照八进制、十进制、十六进制分别输出。

(2)%o按八进制输出,%d按十进制输出,%x按十六进制输出。

(3)\是转义符,\n表示回车换行。因此一行的内容被分成了3行。

划重点

输入数字17,按照不同的进制输出了不同的结果。从我们最熟悉十进制开始,一起研究一下进制。

①熟悉的十进制:

插图

11、12、13、14、15、16、17

②再看看八进制:

插图

注意

这里的17,是八进制进位1,相当于8+7=15,而不是十进制的17。

插图

这里的20,拆分成进位的2和数字0,也就是十进制的数字16=2×8。

继续计数。

八进制的21对应的是十进制的17。

③现在攻克十六进制:

十六进制可以一直数到15呢,但是需要用字母替代。

0、1、2、3、4、5、6、7、8、9、a(十进制的10)、b(十进制的11)、c(十进制的12)、d(十进制的13)、e(十进制的14)、f(十进制的15)。

插图

加1得到的十六进制数值11就对应十进制的数值17啦!这里的11拆成1和1,第一个1代表十进制16。

敲黑板

①探寻进制的奥秘,拆解十进制数字2023。

在十进制里面只有数字0~9,当继续计数就需要进位,这时10就诞生了。

插图
插图
插图

十进制的规则就是满十进一,进1位相当于×10,进2位就是×10×10,进3位就是×10×10×10。

插图

现在一起来拆解2023吧。

2×10×10×10 + 0×10×10 + 2×10 + 3=2023

②探寻八进制的365。

八进制中的10,在十进制中就是1×8 + 0=8。

八进制中的100,在十进制中就是1×8×8 + 0×8 + 0=64。

现在来拆解八进制的365。

插图
插图

十进制转八进制

将十进制转换成其他进制有一种通用的方法:短除法。

来吧,试试将十进制数字275转换成八进制数。

插图

(1)使用短除法不断地除以8,直到商为0。

(2)将余数倒序组合起来,即将4、2、3拼接起来。

(3)得到八进制结果423。

这就是使用短除法进行进制转换的过程。

提出思考

为什么短除法就可以将十进制转成其他进制呢?

十进制的275转换成八进制是423。

进制是逢几进一,这是进制的规则,因此八进制的423也遵循这个规则,逢八进一。

从423变成十进制,这个我们之前已经探索了。

4×8×8 + 2×8 + 3

下面对比一下进制转换的过程。

插图

假设我们将八进制转换成十进制视为一种顺向思维,那么十进制转换回八进制就可以运用逆向思维来思考。

现在你知道为什么短除法可以将十进制转换成八进制了吗?

通过乘得到的答案,再通过除回去,就这么简单。

乘了几个8,反过来就需要除以几个8。

提出思考

怎么没有二进制呢?

printf()没有转换成二进制的格式。但是我们依然可以运用之前学习过的循环来实现。

(1)把二进制数101转换成十进制数:

插图
插图
插图

将计算结果相加:4 + 2 +1=7。

(2)十进制118转换成二进制数:

插图

直到商为0,将余数倒序连接起来,为1110110。

插图

十进制转二进制

插图

翻译助力理解

●pause:暂停。

(1)使用while(true){}不断进行短除法。

(2)短除法分为两步,第一步求余数binary=num % 2,第二步求商num=num / 2。

(3)cout<<binary<<"商为:"<<num表示每一步都将结果输出。

(4)system("pause")表示暂停程序,等待按键继续执行程序,便于我们观察和推进短除法。

运行程序,输入数字:

输出结果为:

1商为:10请按任意键继续. . .

0商为:5请按任意键继续. . .

1商为:2请按任意键继续. . .

0商为:1请按任意键继续. . .

1商为:0请按任意键继续. . .

观察结果,当商为0时,程序不用继续执行,将余数从下往上组合起来,即可得出十进制数21对应的二进制数10101。

敲黑板

研究程序最好的方式就是跟随程序步骤逐一分析。

插图

插图

巩固练习

(1)将十进制数42转换为二进制数,得到的结果是()。

A.001010

B.101010

C.010101

D.110101

(2)八进制数系统中包含的数字范围是0到7。()√()×

(3)请编写一个程序,接收用户输入的十进制整数,将它转换为八进制数和十六进制数,并输出结果。

探索思考

如果程序能在转换完成后自动停止那该多好,这就省去了观察商变化的时间。

阅读以下代码,思考一下为什么改成num>0后,程序就自动停止了呢?

划重点

while(){}的圆括号里面的true变成了num>0,条件发生了变化,之前的true表示条件一直成立,num>0表示只有num大于0条件才成立,那么当商为0时,条件不成立,循环也就不继续了。
插图
插图

拓展探索

之前说到printf()没有二进制的输出格式,现在阅读以下代码学习一下如何快速进行进制转换。

插图

(1)cout<<"二进制表示:"<<bitset(num)<<endl:这行代码用于将num以二进制表示。它使用了bitset类,将整数num转换为一个包含二进制的字符串,并输出到标准输出流cout中。sizeof(int)*4用于指定二进制字符串的长度,将4分别改成2和8,运行程序观察字符串长度的变化。

(2)cout<<"八进制表示:"<<oct<<num<<endl:表示使用oct控制符将整数num以八进制格式输出。

(3)cout<<"十六进制表示:"<<hex<<num<<endl:表示使用hex控制符将整数num以十六进制格式输出。

插图