《C语言程序设计:问题与求解方法》——1.1节二进制简介

简介:

本节书摘来自华章社区《C语言程序设计:问题与求解方法》一书中的第1章,第1.1节二进制简介,作者:何 勤,更多章节内容可以访问云栖社区“华章社区”公众号查看

1.1 二进制简介
为了从整体上把握计算机的基本工作原理,并为后面的编程学习奠定扎实的基础,读者有必要先对数字信号、二进制及其相关知识有比较清晰的、整体的了解。

1.1.1 二进制与二进制数的基本概念
二进制就是只能用数字“0”和“1”来进行计数的数字系统。二进制加法运算的重要规则是: 1+1=10 ,即两个1相加,就产生了向高位的进位,即“逢二进一”(做减法时则是“借一当二”),类似于十进制中的“逢十进一”(做减法时则是“借一当十”)。其他二进制加法规则更简单:0+0=0、0+1=1、1+0=1。二进制与十进制、十六进制的对照如表1-1所示。


219c2a81820f3e63bf1f4c8e8c7729cac28facb8

延伸与拓展:二进制的算术运算规则非常简单。这种简单性是计算机采用二进制的一个重要原因。如何用逻辑门电路(在当代,主要是用大规模集成在硅芯片上的晶体管逻辑门电路)来构成计算机中的二进制算术运算和逻辑运算电路这部分内容并不难懂,感兴趣的读者请参阅本书末尾列出的参考文献。
与十进制数类似,在一个二进制数中,靠左边的数字是高位数,靠右边的数字是低位数。其中最左边的位称为最高位。
我们经常用一对圆括号括住一个数值,并在圆括号外面加一个整数下标,用此下标来表示一个数值是几进制数(但是对于十进制数,常常省略圆括号和下标)。比如,(1011)16是一个十六进制数,而(1011)2是一个二进制数。
二进制数的多项式展开表示
对于一个十进制整数,比如3785,其数值可用以下的多项式展开来表示:

3785=3×103+7×102+8×101+5×100(1) 

我们把(1)式中10的几次方称为权重,权重左边的乘数称为系数。(1)式中共有4个系数,从左到右依次是“3”、“7”、“8”、“5”,权重依次分别是103、102、101、100。
可见,用这种记数法表示数值数据时,越左边的系数所对应的权重越大。权重中的基数(即底)与表示该数的进制是一样大的,在这里都是10。
类似的,任意一个二进制整数,其数值也可用多项展开式来表示。比如,二进制整数1011可表示为

(1011)2=1×23+0×22+1×21 +1×20(2)

(2)式中系数从左到右依次是“1”、“0”、“1”、“1”,而权重依次分别是23、22、21、20。
展开式中系数的最大值一定比进制数小1。比如,在十进制计数系统中,系数的最大值是9,而在二计制计数系统中,系数的最大值是1。
下面我们先来熟悉一些与书写、存储或传输一串二进制数有关的术语。

1.1.2 与二进制数相关的术语:位、位串、字节
1.位
书写、存储或传输单个的二进制数字称为位(bit)。单个“位”中的数字不是0就是1,不可能有其他数字。
任何一个只能处在两个不同稳定状态的电子元件(电容、触发器等)或者某种(比如均匀覆盖着磁性颗粒的)介质表面上的一个小点,都可以用来(间接)表示和存储一个“位”。
2.位串及其长度
多个二进制数顺序排列在一起称为位串(有些教科书将其称为“位模式”)。位串中含有的数字总个数称为位串的长度。比如,位串100110的长度是6。处于位串左边的位称为高位,位于位串右边的位是低位,位于位串最左边的位称为最高位。
3.度量位串长度的基本单位—字节
“位”这个二进制的度量单位太小,用起来很不方便。现代的大多数计算机和一些数字处理设备通常是以长度为8的位串—字节(Byte)来作为度量(部件或设备的)数据存储容量大小的一种基本单位。
把长度为8的一个位串称为一个字节,长度为16的一个位串称为2个字节。长度为n的位串一共有n/8个字节。也就是说,一个位串的长度,既可以用位串中的总位数来度量,也可以用位串所具有的字节数来度量。
延伸与拓展:二进制数据存储和传输的其他一些常用单位
“字节”这个基本单位的大小是“位”这个最小二进制单位的8倍,但是在很多场合仍然还是显得太小,更大的常用单位有(在各种资料中,经常用字符B来表示字节Byte,用K来表示数值1024):
千字节: 1KB=1024B=210B
兆字节: 1MB=1024KB=210KB=220B=1048576 B(约为一百万字节)
千兆字节: 1GB = 1024MB=210MB=230B=1073742814 B(约为十亿七千多万字节)
注意:相邻单位之间都是1024倍的关系,而不是1000倍的关系。
我们常常会看到一些数据存储设备在标识其数据存储容量时使用KB(千字节)、MB(兆字节)或GB(千兆字节)。
不过,在网络和通信领域,人们还是习惯用“位”作为数据传输的基本单位。所以,通常所谓的10兆宽带网,并不是每秒能够传输10MB(10485760字节)的数据,而是每秒传输10×106位(bit)。也就是说,在网络通信领域,“兆”这个名词就是精确地等于一百万(即106)。
4.位串的通常传输方式—并行或串行
一个长度为n的位串,既可以用n根并排的导线同时进行传输,每根导线传输一个位,即并行传输(这种方式的传输速度很快,但要用多根导线);也可以用一根导线,分为n个相等时间段,一位一位地依次先后进行传输,即串行传输(这种方式的传输速度较慢,但只要用一根导线)。

1.1.3 数和码的含义与区别
如果计算机只能够对一些数值进行运算—在计算机刚发明的早期年代,确实就是如此—那么它的应用范围就必然很窄。现代计算机的应用范围几乎深入人类社会生产生活的方方面面。其根本原因在于:现代计算机不仅能够对“数值”进行运算,还能够借助于各种软件和硬件,对间接表示世界上各种各样事物的“码”进行不同的处理。也就是说,同样的一个位串,既可以用来表示数值,也可以用来表示各种不同事物的“码”。
所以,我们想要真正懂得计算机并且学好编程,就不仅要熟悉二进制的“数”,还必须对一些常见的二进制的“码”有清晰的了解。
1.十进制的数和码
我们先来通过一个例子,说明十进制数字系统中数与码的区别。
如果3785用于表示数,则越高位(即越左边的位)的数字越重要(因为权重越大)。而3785用来表示非数值的码,则每一位数字都同样重要。码值仅相差一,所表示的文字(或代表的意义)就可以有巨大的区别(比如,3785可代表汉字“大”,而3786可代表汉字“小”)。
虽然十进制3785只能直接表示唯一的一个非负整数,这个数的值是三千七百八十五;但是,同样一个十进制的数字串“3785”,通过某种编码,可以表示的事物种类却是无限制的:码3785既可以表示一个汉字,也可以表示任何码值为3785的事物。
2.二进制的数和码
与十进制一样,二进制数与二进制码也有类似的区别。只不过在二进制中,只能用数字0和1组成的位串来表达任何大小的数值或者表示具有任何含义的码。
(1)一位二进制的数和码
如果用单个位来表示整数值,只能直接表示0和1这两个值中的一个。如果用单个“位”来表示码,则能够用来对任何(同属一种类型的)两种不同事物制定编码规则。比如,用0表示“假”, 用1表示“真”;用0表示状态“关”,用1表示状态“开”; 用0表示“是”,用1表示“否”;用0表示“取物品”, 用1表示“存物品”;用0表示“黑”,用1表示“白”等。
(2)两位二进制的数和码
如果用长度为2的一个位串来直接表示整数值,则只能够表示00(其值等于0)、01(其值等于1)、10、11这4个二进制非负整数值中的某一个。如果用长度为2的位串来进行编码,由于一共有00、01、10、11这4(即22)个码值可以使用,则能够用来对属于同一类型的4个不同的事、物(或状态)制定编码规则。比如,{煎,炒,蒸,煮 }、{加,减,乘,除}、{班主任,老师,家长,朋友}、{A,B,C,D}、{–2,–1,0,1}、{宿舍,教学楼,食堂,图书馆}、{向左,向右,前进,后退}等,都可用长度为2的二进制码来间接表示。
【例题1.1】编码和解码的一个实例。
通过制定一个编码规则,比如,规定用00表示“D”、01表示“C”、 10表示“B”、11表示“A”,就可以构成一张用4个码来表示4个字符的编码解码表,见表1-2。
用严格的数学术语来讲,所谓制定编码规则,就是规定了一张两个集合{00,01,10,11}与 {A,B,C,D} 之间的所有元素的一对一的映射表而已。
表1-2 4个字符的一张编码解码表


452d556805ce49c5f7729632462c3d63486f7f86

有了这张编码解码表,对字符串“CAB”进行编码后,就可以用码值构成的二进制位串“011110”,在二进制的数字信号处理设备中间接地存储和传输这个字符串。
到达目的地后,接收方也要具有同样的一张“字符编码解码表”,才能将接收到的二进制位串翻译成它的本来意义。比如将二进制位串011110翻译成字符串“CAB”,这个过程称为解码。
(3)长度为n的二进制的数和码
长度为n的位串可以表示的最大二进制非负整数111…1(一共n个1)究竟是多大呢? 这很简单,将由n个1构成的此二进制数加上1,可得到100…0(1的后面一共有n个0)。由这个数的多项式展开可知,它的大小就是2n。因此二进制整数111…1(一共n个1)的大小为2n–1。
因此,如果用长度为n的位串来直接表示一个非负整数,则可以表示的二进制数值从小到大依次是0、1、10、11、…、1111…11(一共n个1,其值等于2n-1),一共有2n个数,则能够用来对任意的2n个同类事物所构成的集合制定一对一的编码规则。
3.世上的绝大多数事物都可通过编码来间接表示
用一个位串只能够直接表示一个非负整数,有符号整数都不能直接用位串来表示。但是,用位串作为码可以间接表示事物的种类却是无限的,世界上的一切可数的事物都可以用码来间接表示,不可数的事物可以用码来近似表示(如何用位串来表示实数、图像和声音请参见后面的内容)。
延伸与拓展:
无效码(或称为非法码)
在可使用的码比(要进行编码的)集合中的元素多的情况下,就会存在一些无效码,这些无效码不代表集合中的任何一个元素。究竟哪些是无效码,是由具体编码规则决定的。
比如用长度为3的位串来对某个集合(中的所有元素)进行编码,可用的码值一共有8(即23)个,集合中如果只有5个元素,那么必然有3个码是无效码。
一般情况下,长度为n的位串一共有2n个码,如果用来对m个元素构成的集合进行编码,而且2n大于m,则总共有2n–m个无效码。
不定长度编码
还有一种码的长度不一样的编码方式,常常用比较短的码表示集合中经常出现的元素。比如哈夫曼编码就是一种不定长度的编码,详细内容请参见相关文献。
4.ASCII码表
英文文件中出现的常用字符,不仅有26个大小写英文字符,还有10个阿拉伯数字字符,另外还有一些用作标点符号的字符(“,”,“.”,“!”等),所有这些字符加上通信过程中需要使用的符号和表示计算机输入输出设备动作的一些特殊空白字符(比如回车、换行、退格等)一共有128个。对于这些字符构成的集合,可用长度为7位的二进制进行编码,历史上曾有多种编码方案,现代最常用的是ASCII编码解码表(简称ASCII码表),即美国信息交换标准代码(参见附录B)。
下面将简要介绍计算机的基本工作原理,为读者学习用高级语言编程奠定坚实的理论基础。对计算机工作原理更深入一步的讲解请参见第11章。

相关文章
|
19天前
|
存储 网络协议 算法
【C语言】进制转换无难事:二进制、十进制、八进制与十六进制的全解析与实例
进制转换是计算机编程中常见的操作。在C语言中,了解如何在不同进制之间转换数据对于处理和显示数据非常重要。本文将详细介绍如何在二进制、十进制、八进制和十六进制之间进行转换。
29 5
|
23天前
|
传感器 人工智能 物联网
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发,以及面临的挑战和未来趋势,旨在帮助读者深入了解并掌握这些关键技术。
40 6
|
2月前
|
Java 编译器 C语言
【一步一步了解Java系列】:Java中的方法对标C语言中的函数
【一步一步了解Java系列】:Java中的方法对标C语言中的函数
30 3
|
3月前
|
C语言
C语言程序设计核心详解 第四章&&第五章 选择结构程序设计&&循环结构程序设计
本章节介绍了C语言中的选择结构,包括关系表达式、逻辑表达式及其运算符的优先级,并通过示例详细解释了 `if` 语句的不同形式和 `switch` 语句的使用方法。此外,还概述了循环结构,包括 `while`、`do-while` 和 `for` 循环,并解释了 `break` 和 `continue` 控制语句的功能。最后,提供了两道例题以加深理解。
104 7
|
3月前
|
存储 C语言
C语言程序设计核心详解 第十章:位运算和c语言文件操作详解_文件操作函数
本文详细介绍了C语言中的位运算和文件操作。位运算包括按位与、或、异或、取反、左移和右移等六种运算符及其复合赋值运算符,每种运算符的功能和应用场景都有具体说明。文件操作部分则涵盖了文件的概念、分类、文件类型指针、文件的打开与关闭、读写操作及当前读写位置的调整等内容,提供了丰富的示例帮助理解。通过对本文的学习,读者可以全面掌握C语言中的位运算和文件处理技术。
|
3月前
|
存储 C语言
C语言程序设计核心详解 第七章 函数和预编译命令
本章介绍C语言中的函数定义与使用,以及预编译命令。主要内容包括函数的定义格式、调用方式和示例分析。C程序结构分为`main()`单框架或多子函数框架。函数不能嵌套定义但可互相调用。变量具有类型、作用范围和存储类别三种属性,其中作用范围分为局部和全局。预编译命令包括文件包含和宏定义,宏定义分为无参和带参两种形式。此外,还介绍了变量的存储类别及其特点。通过实例详细解析了函数调用过程及宏定义的应用。
|
3月前
|
C语言
C语言程序设计核心详解 第三章:顺序结构,printf(),scanf()详解
本章介绍顺序结构的基本框架及C语言的标准输入输出。程序从`main()`开始依次执行,框架包括输入、计算和输出三部分。重点讲解了`printf()`与`scanf()`函数:`printf()`用于格式化输出,支持多种占位符;`scanf()`用于格式化输入,需注意普通字符与占位符的区别。此外还介绍了`putchar()`和`getchar()`函数,分别用于输出和接收单个字符。
|
3月前
|
存储 算法 C语言
C语言程序设计核心详解 第一章:数制及转换与ASCII码
本专栏旨在夯实C语言基础,涵盖基础知识与进阶内容,助力解决自命题考试和考研问题,为数据结构与算法设计奠定坚实基础。内容包括数制及其转换、ASCII码、内存管理、机器码等,重点讲解二进制、八进制、十六进制的概念与转换方法,并介绍C语言的结构、数据类型和标识符规范。
|
3月前
|
存储 人工智能 C语言
C语言程序设计核心详解 第八章 指针超详细讲解_指针变量_二维数组指针_指向字符串指针
本文详细讲解了C语言中的指针,包括指针变量的定义与引用、指向数组及字符串的指针变量等。首先介绍了指针变量的基本概念和定义格式,随后通过多个示例展示了如何使用指针变量来操作普通变量、数组和字符串。文章还深入探讨了指向函数的指针变量以及指针数组的概念,并解释了空指针的意义和使用场景。通过丰富的代码示例和图形化展示,帮助读者更好地理解和掌握C语言中的指针知识。
130 4
|
3月前
|
存储 人工智能 C语言
C语言程序设计核心详解 第六章 数组_一维数组_二维数组_字符数组详解
本章介绍了C语言中的数组概念及应用。数组是一种存储同一类型数据的线性结构,通过下标访问元素。一维数组定义需指定长度,如`int a[10]`,并遵循命名规则。数组元素初始化可使用 `{}`,多余初值补0,少则随机。二维数组扩展了维度,定义形式为`int a[3][4]`,按行优先顺序存储。字符数组用于存储字符串,初始化时需添加结束符`\0`。此外,介绍了字符串处理函数,如`strcat()`、`strcpy()`、`strcmp()` 和 `strlen()`,用于拼接、复制、比较和计算字符串长度。