计算与计算机

  从千年前的石器时代、青铜器时代、铁器时代到近现代的蒸汽时代、电气时代、原子时代再到如今的信息时代,人类工具经过了一代又一代的发展,使得社会资源也得到了大大提升(感谢先人们的智慧),信息时代的工具载体是我们早已习以为常的计算机,俗话说:工欲善其事,必先利其器,了解下计算机的基础概念原理还是很有必要的。

可计算性

  在数学中,可计算性是函数的一个特性;在计算机中,可计算性是指一个实际问题能否用计算机来解决。在计算机还没发明出以前,也是有计算装置的,比如算盘(计算内容比较定向),还有我们的大脑也可以说是一个计算装置。
计算的实现可以抽象为三点:1.对语言的理解和解释(interpretation)2.记录规则、过程及中间结果(memory)3.这个过程可以被执行,可以在不同的过程中切换(programmable)。现在的计算机就是一个通用计算装置,它拥有符号解释功能、过程记忆功能以及可编程功能。
计算思维是将现实问题用算法程序实现,这些程序可以被计算机自动的执行,也就是抽象+自动化。对程序员来说培养计算思维也是相当重要的,我们用代码实现需求,不能只像解数学应用题,还应该尽可能提炼出可复用的基层的一些东西,这么看,抽象能力决定了编程能力。

图灵机

通用计算机的概念最早是由“祖师爷”图灵提出(有一部讲图灵的电影《模仿游戏》,有一个场景,凯拉奈特利演的琼克拉克看到图灵正在制作的机器,惊讶的说,‘你是想做通用计算机?’),通用计算机有数据多样性和程序多样性的特点。
“图灵机”的工作原理:用一条可以无限延展的输入纸带存储指令,有个状态控制器来进行状态转换,能控制纸带上读写头的移动及操作。

冯诺伊曼体系结构

“计算机之父”冯诺伊曼造出了第一台通用计算机ENIAC,它奠定了现代计算机的设计思想:采用二进制;能存储程序并按照程序顺序执行。由于计算机需要可以长期存储输入程序及数据,自动化处理算术运算逻辑运算、控制程序的走向,将结果输出给用户,冯氏结构计算机有五大组成部件存储器 运算器 控制器 输入设备 输出设备。(冯诺伊曼不仅在计算机领域有超凡的成就,在其他领域——逻辑学、物理、化学、金融等也都是大佬级存在,看透世界本质的人啊。膜拜orz。

现代微机结构

冯氏结构一直延续到今天,当代微机结构的核心也是根据其实现。现代计算机主要结构为:CPU+内存+主板+外设(辅存、输入输出设备)。
cpu通过内部总线连接集成了控制单元CU、运算逻辑单元ALU、寄存器Register
寄存器容量很小,包括通用寄存器(存储单元)和专用寄存器,通用寄存器存储原始数据、中间结果等,专用寄存器存储计算机当前状态。因其在cpu内部,访问寄存器的速度>内存速度>硬盘>外部辅存(u盘等)。
控制单元的功能是分析指令、传送指令及数据、产生时序逻辑来控制和协调整个cpu工作。内部包括:程序计数器PC(下条指令地址,自加1)+指令寄存器IR(当前执行指令)+指令译码器ID(根据IR内容决定进行何种操作)+操作控制器OC(取指令、取数、控制alu)。cpu的工作就是循环执行指令,一条指令的执行时间为指令周期:取指令-> 译码-> 执行-> 写结果,每一个步骤称为一个节拍。cpu工作的最小时间单位为时钟周期,一个节拍可能花费多个时钟周期,如取指令花费3个时钟周期,时钟频率(主频)=1/时钟周期。
运算逻辑单元ALU:电路实现算术运算和逻辑运算& | ~等。
多核cpu是指一个cpu内包含多个运算单元和控制单元,可共享寄存器。
主存单元是一系列存储数据的单元格,数据按字节顺序存放在单元格中。存储容量=单元格数x每单元的字节数。如32位地址长度,最多的存储容量位2^32,即4gb(满格)。主存地址是从0开始递增的主存单元编号,访问主存就是通过读写主存地址读写单元数据,至少有1字节。

操作系统

在硬件之上,有操作系统来对硬件资源进行管理,包括调度cpu、封装硬件操作,相当于我们和计算机底层硬件中的抹平层。操作系统有两大接口:人机接口+api接口,方便使用。四大任务:进程管理、文件管理、存储管理、设备管理
进程管理就是对cpu的管理,每个运行的程序就是一个进程,操作系统通过进程控制块(pcb)来存储记录当前进程信息:pid、特征(系统or用户进程)、状态(阻塞、就绪or运行中,状态依赖寄存器中内容)、优先级、通信信息(进程间通信关系)、现场保护区、资源分配信息、进程实体信息(程序路径和名称)及其他信息。进程是cpu分配资源的单位,线程是资源使用最小单位,同一个进程的线程共用cpu分配的资源。操作系统的特征是并发和共享,进程调度策略也有很多:先来先读、时间片轮转法、优先级法(抢占式、非抢占式-就绪等待队列首部)、多级反馈队列轮转。
文件管理主要是管理文件内容及属性信息。
计算机开机后会首先复位,然后加载操作系统到内存中,一般内存地址0~某位都是操作系统(bios)。

点击程序运行时发生了什么?

鼠标点击程序图标后,操作系统先从硬盘拷贝预存好的程序指令到内存中,cpu再从内存中读取程序指令并执行。cpu不能直接访问硬盘,必须要经过内存,所以有些大型游戏会对内存容量有很高要求。

程序及语言

程序=指令+数据
机器语言是指计算机可执行的01代码,指令是用机器语言描述的一系列操作,指令集/指令系统:cpu所执行的机器指令集合,包含有操作指令、控制指令、数据移动指令。每个cpu支持的指令集可能不一样,但大多数都支持x86指令集。汇编语言是将机器语言符号化,能被翻译成机器码。高级语言,独立于硬件,面向过程或对象,更接近人类自然语言或数学语言,我们日常的编程语言就是高级语言了,c、c++、js、java、python等。不同高级语言或设计思想或应用场景都有所不同,但像小程序一点技术提升却衍生出N家语言,简直是退化逆向发展,恶心程序员啊,如果有技术协会搞个统一协议就好了。
存储程序的抽象实现过程:编程语言->机器语言->存储硬盘。

最后

  摩尔定律表述计算机效率每18个月翻一倍,得益于硬件的快速发展,现代计算机的变化可谓是日新月异,但其核心原理没有变,深入了解其核心原理,能帮助我们更好的理解拥抱变化,与时俱进。

浅谈现实世界信息数字化

  在我们的计算机中,一切信息(文字、音视频、图片等)都是通过相关的规则转换成0和1的字符串表示,反过来,也能通过对应规则将计算机中这些0和1的编码解析出其代表的真实世界的信息。计算的本质也是将一种字符串通过规则转换成另一种字符串。
  先说说进制,逢n进1,是n进制,像手表时针12进制,秒针60进制。计算机采用的是二进制,在人们日常生活习惯中使用的是十进制,那为什么计算机里却没有采用十进制呢?

  1. 最主要是二进制状态简单稳定,容易被表示,如灯的开关、电压高低等。如果用十种不同电压值表示十进制,就远没有高低电压的二进制稳定。
  2. 完全能处理逻辑,1表示‘是’0表示‘否’,也没浪费状态,十进制就不一样了,浪费了剩余的8个。最完美的公式拥有最简单的符号,而通过任意组合这些简单的符号,能实现所有的逻辑,有点道家大道至简的味道。
  3. 二进制的运算规则比十进制少,如十进制乘法要9*9=81种规则,二进制只有0*00*11*01*1,简化了计算机运算器的内部结构。

各种信息又是怎样用二进制表示的呢?
数字
  数字分为整数、小数、正数、负数。正负数通过最高位0正1负表示,其余为数值位,计算机中的数字用补码表示,这样解决了+0和-0的问题,正数补码为原码本身,负数取反加1,补码的补码是其原码。
  十进制转二进制规则:整数部分,是除2取余法直至0,小数部分是乘2取整直至1。表示方法也分为定点数表示法(整数和纯小数)和浮点数表示法,其中浮点数由尾数和阶码拼接组成。任意一个数 n=m*2^e,m为尾数(纯小数),e为阶码(整数),浮点数 = [有符阶码二进制数\][有符尾数二进制数]。小数位可能一直无法乘到1而无限循环,但二进制位有限,就会造成精度丢失,也就产生了0.1+0.2!=0.3的问题。
  两个正数相加结果超出最高存储范围就会正溢出,负溢出是两负数相加过长。溢出后的值是理论结果mod2^n(n为位数),依据的是同余理论。
一些常见位运算 ~~n n向下取整 n>>1 n/2 向下取整 n<<1 n*2 忽略小数位

文字符号
  计算机字符的转换规则统一遵循ascii码(美国信息交换标准码),128个字符分别表示键盘上的符号,包括数字、英文、运算符、删除回车等。ascii码占一个字节,128个数只需要7位,还剩余一位,则默认首位为0。其他一些国家会使用首位,这样在他们自己的编码集里128~255分别表示他们自己定义的符号。
  中文个数比较多,一个字节完全不能表示尽,所以中文使用两个字节来表示。这样又会有个问题,两个字节中的一个可能和ascii码一样,防止冲突,在机内码中将汉字国标码每个字节最高位都改为1,即机内码=国标码+8080H。
  Unicode(utf-8)是全球通用字符集,也叫万国码、统一码、唯一码,存的字符集数量更多,所以,每个字符分配4个字节。
  平常遇到乱码的情况,就是你当前的字符集不兼容了。

音频
  声音是物体震动产生的声波,再通过介质传播并能被听到的波动现象(百度百科解释)。计算机怎么存储的声音呢?是将声音震动波采样离散、量化离散后生成单个声波点,再将声波点编码成0、1字符串。
采样频率:单位时间内采样次数,单位hz,一般电话是8khz,音乐是44khz,采样频率越高,数据量越大。
量化位数:即采样精度,记录每个采样点需要的二进制位数,单位:位/字节。
声道:一个音频可有单到多个声道,每个声道能存储不同声音信息,电话一般是单声道,音乐是左右双声道,多声道声音更立体更环绕。
比特率:每秒音频包含的数据位数,单位bps。等于采样频率x量化位数x声道数
音频数据量: 比特率x时间

图片
  一张图片是由无数个像素点组成,常说的分辨率axb就是有axb个像素点,也叫位图,栅格图片最小单位,每个像素点存储了一些信息,如位置、颜色、透明度等。其中颜色是如何编码化的呢?现实中任何一种颜色都可以通过三原色(红绿蓝)改变亮度组合而成。亮度是个无限量的概念,怎样通过有限的数据表示它呢?可以将亮度量化成有限的值。比如白天和黑夜是0、1两个,白灰黑是0001or1011三个,依此类推,计算机将三原色中每种颜色的亮度都量化成256个数值(0~255),然后将这些量化后的数值组合起来,就可以表示某个颜色都信息值,这就是常见的rgb颜色模型,如rgb(0,0,0)。
  单色图像每个像素点只有1个bit,计算机用1表示黑色,0表示白色
  灰度图像每个像素点4个bit,可以表示0000~1111 16种颜色
  真彩色图像基于rgb模型图像,每个像素点占8bit*3,可表示256*256*256种颜色,完全满足肉眼需求,每个bit还能富余1位,so最高位都赋值为0。
  对于rgba模型多出的a值表示的是透明度,取值范围0~1,表示这个像素点透明的程度。
  这些像素的颜色需要通过显示器来展示,显示器上安有能发出三原色光线的元器件,也能改变亮度,配合上图片每个位图的各项信息,最终能呈现出物理世界的图片。这就有了另一个问题,同一个图片,在某些场景下,为何会出现模糊的情况?
  默认一个位图对应一个物理像素,当一个位图对应多个物理像素时,就会通过就近取色算法(如像素颜色差值)根据附近颜色信息更新一个。如x,y,z横向三个像素点,y色值=(x色值+z色值)/2,导致图片看起来比较模糊。相反,如果一个物理像素对应多个位图,也会造成图片减少锐度、有色差。
Tips:设备物理像素为设备绝对像素,浏览器中css像素(即设备独立像素)为相对像素,pc端浏览器中独立像素和物理像素1:1对应,多倍屏浏览器中一个独立像素对应多个物理像素。移动端切图时候需要额外处理下,设计图的像素值是相对于电脑屏幕1倍图,但对于多倍屏来说,最终像素值要用ui图的值除以设备像素比。border 1px问题可以通过scale解决。

压缩
  压缩分位有损压缩和无损压缩。精度要求高的采用无损压缩,像图片、音视频都采用有损压缩,不影响表达的同时大大减少数据量。比较简单的压缩方法aaaaabbbbccc => 5a4b3c,大大节省了存储空间。

  我们编程的代码通过层层编译解释,最终也成为01表示的机器码。理解了这些基础知识,就很容易把具体事物抽象出来再用编码表示,对我们来说,计算机也就不再是个黑盒的存在了。