【知乎问题】如何让不懂编程的人感觉到编程的魅力

  • 「MoreThanJava」 宣扬的是 「学习,不止 CODE」,本系列 Java 基础教程是本身在结合各方面的知识以后,对 Java 基础的一个总回顾,旨在 「帮助新朋友快速高质量的学习」
  • 固然 不论新老朋友 我相信您均可以 从中获益。若是以为 「不错」 的朋友,欢迎 「关注 + 留言 + 分享」,文末有完整的获取连接,您的支持是我前进的最大的动力!

知乎问题:如何让不懂编程的人感觉到编程的魅力?html

连接:https://www.zhihu.com/question/406408447java

Part 0. 前言

问一个相似的问题:「如何让不懂篮球的人感觉到篮球的乐趣?」git

很明显,答案取决于人。程序员

对于某些人来讲,编码多是乏味而艰巨的,但对于有些人则是很是有趣且有益的。github

一般状况下,编写好代码以后,咱们很难评判编码的过程是无聊仍是有趣的。web

可是咱们能够经过更好地了解 「计算机编程是什么」,所以您能够本身来评判这是否让你感到乐趣。算法

就当代的发展水平来讲,只要有电的东西就会涉及到编码;编程

Part 1. 计算机发展简史 | 解决实际的问题

一切的开端 | 织布机

衣食住行是人类的基本需求,世界各地都有纺织和织机的发明。架构

如何提高纺织的效率,成为一个很重要的课题。app

纺织的原理

「针织物」 不一样,「机织物」 由两条或两组以上的相互垂直的两个系统纱线或丝线构成,纵向的纱线经纱横向的纱线纬纱

经过两条线不一样规律的交错,就会造成不一样的颜色和排列的变化,也就会带来不一样的纹样。

最原始的织机是手动完成的。

后来人们发现,织物纹样的变化老是按照必定规律排列完成的,到了战国时期,就发明了 多综式提花织机,经过 综框 来完成这一项工做:

这或许就是最原始的 编码:经过把 提起规律相同的经纱 穿入 同一个综框的综丝 中,来达到当某一个综框提起时 (经过脚踏板完成),表达某一个特定纹路的线被提起,也就完成了 特定纹路的编织,加快了工做效率。

织布机的更进一步 | 束综提花织机

不过采用综框也有一个明显的限制,那就是 没法织出比较复杂的纹样,由于纹样复杂则表明着须要更多的经纬纱以及经纱提高的规律更复杂,意味着可能引入成百上千次纬纱才能完成一个循环。

若是仍然采用综框控制纱线提高,则可能须要成百上千个综框,这在机械上实现是很是困难的,所以便有了 束综提花织机

束综提花织机没有综框,而是被 设计成两层,每一根经纱会穿入综丝中实现 单独的控制上层 的人将须要提起的经纱提起,而 下层 的人则再经纱提起后经过梭子将纬纱送入织口,并用打纬装置将引入的纬纱打牢。

然而一般来讲,这类织机上会有成千上万根纬纱,纹样复杂,因而聪明的老祖宗们发明了 花本

简单来讲,花本存储了纹样信息。

图中花本的竖线链接穿入了经纱的综丝,横线存储了每一次引入纬纱时提花信息,当竖线越过横线覆盖在横线前方时,代表对应的经纱要被提起。

这就有点儿 编码规则 的意思。

会说话的「机器」 | 雅卡尔织布机

上面说到的束综提花织机虽然是一大进步,但可想而知的是,它仍然效率缓慢而且织布工人的劳动量很是大,也很是辛苦。

时间来到 18 世纪的欧洲。1725 年,布乔 开拓性的使用 打孔纸带 来控制经线的提起和放下,从而让织出花样成为一种半自动化的工做:

历史上第一次,机器可以读出存储介质中的内容,而且照其行事。

在布乔提出构想 65 后的 1790 年,约瑟夫·玛丽·雅卡尔 根据前人的成果设计了新式织机,最终于 1805 年完成了首台 自动提花织机

雅卡尔将 穿孔纸带 改进为 穿孔卡片,根据纹样图案在卡片上打孔,经过孔的有无 带动一系列机械运动装置来 控制经纱的提高,一张卡片对应循环内一次引纬时经纱提高的信息,引纬完成后,可经过脚踏板控制卡孔卡片转动,下一张卡片翻转至工做位置以控制新一次引纬的提花:

雅卡尔织机大幅度节省了时间和工做量 (全自动且效率是以前的二十五倍),并且只需一位工人,很快就被普遍使用在工厂生产中,雅卡尔也荣获了拿破仑授予的荣誉勋章。

穿孔卡片控制织物纹样的设计成为了程序设计思想的萌芽,为信息技术的发展开展了一条新的道路。

程序设计思想开始萌芽 | 差分机

时间来到 19 世纪初,法国人 巴贝奇 (Chanles Badbbage) 在贾卡织机的启发下,设计并制造了 差分机

故事背景

18 世纪末,法国政府在开创米制以后,决定在数学中统一采用十进制,竟奇葩地想把本来 90 度的直角划分红 100 度、把本来 60 秒的 1 分钟划分红 100 秒,尽管从如今看来这样的想法绝逼是一种倒退,但他们在当时真就实施了。这一改制带来的不光是人们在使用时直观上的别扭,本来制做好的数学用表 (如三角函数表) 都须要所有重制。

法国政府将这项丧心病狂的工程交给了 数学家普罗尼 (Gaspard de Prony),普罗尼正头疼着要如何才能完成这项艰巨的任务,忽然想起著名经济学家 亚当·斯密 (Adam Smith) 的那本《富国论》,他决定采用书中提出的 劳动分工 的作法,将制表的工做人员分红三组:

  • 第一组 由五六名牛逼的数学家组成,他们负责制定运算中所需的公式;
  • 第二组 由九到十个擅长数学的人组成,他们负责计算出一些关键数据,并把第一组制定好的公式进行简化;
  • 第三组 由约一百名计算人员组成,他们利用第二组提供的关键数据和公式,作最简单的加减操做就能得出最终结果。

第三组的工做简单到什么程度,就是他们甚至都不知道本身正在算什么玩意儿,事实上他们的文化程度大部分都不高,里头好多都是理发师、失业人员什么的。可见即使文盲都能完成的计算,在那个时代仍是得依靠人力去作。

而为了保证用表的正确性,普罗尼要求 每一个数至少算两遍,而且 要在法国的不一样地点用不一样的方法计算。这项劳民伤财的工程整整进行了十年才完成,然而不幸的是,最终的表里仍然有错。说到这一点,能够说,那个时代基本没有一版数学用表是彻底正确的,有些版本甚至错误百出,要知道数学用表出错有时后果会很严重,好比航海表一出错就可能直接致使船毁人亡。

巴贝奇 在了解到普罗尼的事迹后泪流满面,决心要作一套彻底正确的数学用表,为达目的,他尝试了各类减小错误的手段,好比调整纸张和墨水的颜色以提升数字的识别度,直接拿现有的多个版本的表进行誊抄、比对、让不一样人员反复校对,在 1827 年出版了一个版本,结果里头仍是有错。只要是人为的就没有完美的,巴贝奇完全跪了,他发誓要造一台机器,让机器去生产数学表。

这就是史上著名的 差分机 了。

伦敦科学博物馆·差分机设计图纸&半成品:

第一台真正意义上的电脑 | 分析机

尽管没能亲手实现差分机,但巴贝奇并不会气馁,或者说他原本就是根本停不下来的那种人。明知实现不了,巴贝奇仍在一刻不停地改进着本身的设计,直到有一天,他构思出了一种空前的机器——分析机,正式成为现代计算机史上的第一位伟大先驱。 (Father of computing)

1834 年,分析机概念诞生之际,巴贝奇本身都为之感到无比震惊。在此以前,任何一台计算机器都只能完成其被预约赋予的计算任务,要么是简单的加减乘除,要么像差分机那样只能作差分运算,它们都属于 calculator,而分析机才是真正的 computer,它不局限于特定功能,而居然是可编程的,能够用来 计算任意函数——现代人不管如何也没法想象在一坨齿轮上写程序是怎样一种体验吧!

巴贝奇设计的分析机主要包括三大部分:

  1. 用于存储数据的计数装置,巴贝奇称之为 “仓库”(store),至关于如今 CPU 中的存储器,这部分是从差分机上的计数装置改进而来的,咱们很容易想象它的模样;
  2. 专门负责四则运算的装置,巴贝奇称之为 “工厂”(mill),至关于如今 CPU 中的运算器,这部分的结构相对复杂,巴贝奇针对乘除法还作了一些优化;
  3. 控制操做顺序、选择所需处理的数据和输出结果的装置,巴贝奇没有起名字,因为其呈桶状,咱们能够叫它 “控制桶”,控制桶显然至关于如今 CPU 中的控制器

以上三部分,加上巴贝奇并无疏漏的输入输出设备,咱们惊讶地发现,分析机的组成部分和如今冯·诺依曼架构所要求的五大部件如出一辙!

巴贝奇另外一大了不得的创举就是将 穿孔卡片(punched card) 引入了计算机器领域,用于控制数据输入和计算,从那时起,到第一台电子计算机诞生为止,期间几乎全部的数字计算机都使用了穿孔卡片。

整个分析机就是在相似这样的齿轮和拉杆做用下实现可编程运算的:先从数据卡片读入数据到存储器,再将存储器中的数据传输到运算器,运算器算完后又将数据传回存储器。

惋惜的是,巴贝奇穷其一辈子也没能真正把分析机作出来,留给后世的又是一台模型机和两千多张图纸,以及这样一段遗言:

「若是一我的不因我一辈子的借鉴而却步,仍然一往直前制成一台自己具备所有数学分析能力的机器……那么我愿将个人声誉绝不吝啬地让给他,由于只有他可以彻底理解个人种种努力以及这些努力所得成果的真正价值。」

伦敦科学博物馆·分析机设计图纸&模型机:

穿孔时代的到来 | 制表机

1790 年开始,美国每 10 进行一次人口普查。百年间,随着人口繁衍和移民的增多,从 1790 年的 400 万不到,到 1880 年的 5000 多万,人口总数呈爆炸式地增加。

1790~1880 年美国人口增加曲线

不像如今这个的互联网时代,人一出生,各类信息就已经电子化、登记好了,甚至还能数据挖掘,你没法想象,在那个计算设备简陋得基本只能靠手摇进行四则运算的 19 世纪,千万级的人口统计就已经成了当时政府的 “不能承受之重”

1880 年开始的第 10 次人口普查,历时 8 年才最终完成,也就是说,他们在休息两年以后就要开始第 11 次普查了,而这一次普查,须要的时间恐怕要超过 10 年,那第 12 次、13 次呢?原本就是 10 年一次的统计,若是每次耗时都在 10 年以上,这件事情就变得没有意义了。

这可愁煞了当时的人口调查办公室,他们决定面向全社会招标,寻求能减轻手工劳动、提升统计效率的发明。正所谓机会都是给有准备的人的,一位毕业于哥伦比亚大学的年轻人 赫尔曼·霍尔瑞斯 (Herman Hollerith) 带着他在 1884 年申请的专利从众多方案中脱颖而出。

制表机

他发明的机器叫 制表机 (tabulator/tabulating machine),顾名思义,就是专门用来制做数据统计表的机器。制表机主要由示数装置、穿孔机、读卡装置和分类箱组成。

示数装置包含 4 行、10 列共 40 个示数表盘,每一个盘面被均匀地分红 100 格,并装有两根指针,和钟表十分相像,“分针” 转一圈可计 100,“时针” 转一圈则计 10000。可见,整个示数装置能够表达很庞大的数据。

制表机的工做是围绕穿孔卡片展开的:操做员先使用穿孔机制做穿孔卡片,再使用读卡装置识别卡片上的信息,机器自动完成统计并在示数表盘上实时显示结果,最后,将卡片投入分类箱的某一格中,进行分类存放,以供下次统计使用。

穿孔卡片的应用

此前的某一天,霍尔瑞斯正在火车站排队检票,目光不经意落到检票员手中咔咔直响的打孔机上。他发现,检票员会特地根据乘客的性别和年龄段,在车票的不一样地方打孔。愈来愈多的人过检,他进一步确认了这个规律。一个灵感朝他袭来:若是有一张更大的卡,上面有更多的位置能够打孔,就能够用来表示更多的身份信息,包括国籍、人种、性别、生日等等。

这就是用在 1890 年人口普查中的穿孔卡片,一张卡片记录一个居民的信息。卡片设计长约 18.73cm,宽约 8.26cm,正好是当时一张美圆纸币的尺寸,由于霍尔瑞斯直接用财政部装钱的盒子来装卡片。

卡片设有 300 多个孔位,与雅卡尔和巴贝奇的作法同样,靠每一个孔位打孔与否来表示信息。尽管这种形式很有几分二进制的意味,但当时的设计还远不够成熟,并无用到二进制真正的价值。举个例子,咱们如今通常用 1 位数据就能够表示性别,好比 1 表示男性,0 表示女性,而霍尔瑞斯在卡片上用了两个孔位,表示男性就其中一处打孔,表示女性就在另外一处打孔。其实性别还凑合,表示日期时浪费得就多了,12 个月须要 12 个孔位,而常规的二进制编码只须要 4 位。固然,这样的局限也与制表机中简单的电路实现有关。

细心的读者可能发现卡片的右下角被切掉了,那不是残缺,而是为了不放反而专门设计的,和如今的二维码只有 3 个角是一个道理。

这类实用的细节设计在穿孔机上表现得更为出色。下图为一位操做员正在使用穿孔机给卡片打孔的情景,她并不须要在卡片上吃力地搜寻孔位,而是直接对着孔距更大的操做面板打孔,一根杠杆将二者的孔位一一对应。操做面板还作成了弧形,很有一分现在人体工程学键盘的风姿。

在制表机前,穿孔卡片(或纸带)多用于存储指令而不是数据。比较有表明性的,一是雅卡尔提花机,用穿孔卡片控制经线提沉;二是自动钢琴,用穿孔纸带控制琴键压放。美剧《西部世界》中,每次故事循环的开始,都会给一个自动钢琴的特写,弹奏起看似宁静安逸、实则诡异违和的背景乐。

是霍尔瑞斯将穿孔卡片做为 数据存储介质 开来,并开启了一个崭新的 数据处理纪元。后来人们也把这类卡片称为霍尔瑞斯卡片,穿孔卡片和穿孔纸带做为输入输出载体,统治了计算领域整整一个世纪。

单元记录时代

在制表机的高效运转下,1890 年的人口普查只花了 6 年时间。1896 年,霍尔瑞斯成立制表机公司(The Tabulating Machine Company)并不断改进本身的产品,前后与英国、意大利、德国、俄罗斯、澳大利亚、加拿大、法国、挪威、美国波多黎各、古巴、菲律宾等多个国家和地区合做开展了人口普查。

1914 年,制表机公司天天生产的穿孔卡片多达 200 万张。很少久,一些竞争对手逐渐起家,历史迎来了繁荣的数据处理时代。它们的产品也再也不局限于人口普查,逐渐扩展到会计、库存管理等一些一样须要跟大数据打交道的领域,这些机器做为制表机的后裔被统称为单元记录设备(unit record equipment)。

围绕穿孔卡片的制卡、读卡、数据处理和卡片分类是它们的标准功能,穿孔机、读卡器、分类器是它们的标准配置。这些部件的自动化程度愈来愈高,好比手动的读卡装置很快被自动读卡机所取代,读卡速度从每分钟 100 张逐步提升至每分钟 2000 张。随着识别精度的提升,卡片的孔距也愈来愈小,具备 80~90 列孔位的卡片成为主流,有些卡片的孔位甚至多达 130 列。

20 世纪典型的 80 系穿孔卡片

机器的功能也逐渐强大,再也不只是简单地统计穿孔数目,减法、乘法等运算能力陆续登场。1928 年,哥伦比亚大学的科学家们甚至用单元记录设备计算月球的运行轨迹,他们在 50 万张卡片上打了 2000 万个孔,彰显着单元记录设备的无限潜力。

机器的电路实现愈来愈复杂,但同时也愈来愈通用。1890 年所用的那台制表机的 线路是固定的,遇到新的统计任务,改造起来十分麻烦。

1906 年,霍尔瑞斯便引入了接插线板(plugboard)——一块布满导电孔的板卡,可经过改变导线插脚在板上的位置改变线路逻辑。试想一下,接插线板的内部已经布好了具备各类功能的线路,但它们都处在断开状态,各自链接着接插线板上的某两个孔位,像一窝嗷嗷待哺的小鸟长大着嘴巴,外部的导线就像美味的虫子,当虫子的头尾分别与小鸟的上喙和下喙接触,线路就被导通,这只小鸟就开始工做了。如此,每次使用就能够激活不一样的 “小鸟”,从而完成不一样的任务。这已是一种可编程性的体现。

1911 年,制表机公司与另外 3 家公司合并成立 CTR 公司 (Computing-Tabulating-Recording Company),制表机公司做为其子公司继续运营到 1933 年。

1924 年,CTR 改名为 国际商业机器公司International Business Machines Corporation),就是如今大名鼎鼎的 IBM 公司。可见,在现在众多年轻的 IT 公司中,拥有百年历史的 IBM 是位当之无愧的前辈,它完整地参与和见证了整个现代计算机的发展史。IBM 保持了制表机公司在单元记录市场的龙头地位,到 1955 年,其天天生产的穿孔卡片多达 7250 万张。

1937 年开始,单元记录设备逐步电子化,与电子计算机的界线渐渐模糊,并最终为后者让路。随着 1976 年 IBM 一型最核心的单元记录产品的停产,短暂的单元记录时代也宣告谢幕,它仿佛是电子计算时代来临前的预演和铺垫,许多设计被沿用下来,好比穿孔卡片和接插线板。

有趣的是,即便电子计算机逐渐普及,许多机构因为用惯了单元记录设备,迟迟不肯更换,少数机构甚至一直用到了 21 世纪。

一句话总结

编程可以帮助咱们解决一些很是实际的问题,用一种很是酷的方式。

感兴趣也能够扩展阅读一下:改变世界的代码行

Part 2. 二进制和 CPU 原理 | 编码中蕴藏的智慧

原来,咱们是这样计数的

在讨论「二进制」和「CPU 如何工做」以前,咱们先来讨论一下咱们生活中最稀疏日常的 数字,咱们与之频繁地打交道:一个约定的时间、一件商品的价格、一我的的身高....却不多有人细细想过,这些数字是如何表达出来的?为何你理所固然地把 1024 理解为「一千零二十四」而不是别的含义?

也许你从未想过,在这简单的记数中,沉淀着人类的大智慧。

一进制计数法

早在数字的概念产生以前,人类就学会了使用树枝、石子、贝壳等天然界随处可见的小物件表示猎物的、果实的、部落人口的数量。好比在某个角落堆上一堆石子,每打到 1 只猎物,就扔 1 颗石子进去,每吃掉 2 只猎物,就从中取走 2 颗石子。他们并不在乎石子的总数,只是时不时地瞅一眼,心底大体有数。

其实这是一种最朴素的记数方式,数学家称之为 一进制记数法(unary numeral system)。咱们把它符号化一下,好比用斜杠 / 来表示:

  • 1 就是 /
  • 2 就是 //
  • 4 就是 ////

好像没毛病,咱们平时掰手指用的就是这种记数法,但数字一大,场面就要失控了。

符值相加记数法

为了解决记录大数的问题,因而咱们得发明一些其余符号来表示更大的数值,好比用横杠 - 表示 10,用十字 + 表示 100。那么:

  • 16 就是 -//////;
  • 32 就是 ---//;
  • 128 就是 +--////////;

漂亮....这种靠符号类型和符号数量表示数字的方法被称为 符值相加记数法(sign-value notation),古埃及和古罗马用的都是它,只不过符号各不相同。

古埃及的记数符号:

1 10 100 1000 10000 100000 1000000

1024 在古埃及就写做:

你会发现,符值相加记数法的一大优势是,符号的顺序能够任意打乱,数字含义不受影响。我国藏族曾用石子表示 1、木棍表示 10、果核表示 100、蚕豆表示 1000、瓦片表示 10000,那么,当你把 1 颗蚕豆、2 根木棍和 4 颗石子胡乱地攥在手里,别人依然知道它们是 1024

古罗马的作法略有不一样,他们对五进制情有独钟:

1 5 10 50 100 500 1000
I V X L C D M

这些符号沿用至今,想必你们(至少对前 3 个)都比较熟悉,许多钟表仍保留着使用罗马数字的习惯,1~12 分别表示为:IIIIIIIVVVIVIIVIIIIXXXIXII。你会发现,罗马记数法是符值相加记数法的变种,由于它不光「相加」,还「相减」。这种方式就不容许符号乱序了,IVVI 表示的是不一样的数字。

那罗马人何苦要使用这种更复杂的记数法呢?无非是为了读写方便。一样表示 9IXVIIII 更简洁。

其实有一种更好使的方法——用另一些列符号来表示符号的数量。好比用 A 表示 1 个符号,用 B 表示 2 个符号,以此类推,用 I 表示 9 个符号。

如此,上文表示 256++-----////// 就能够写做 B+E-F/。你必定感受莫名其妙,这种写法哪里方便了。其实中文的数字表示就是这种形式,只不过咱们用得太习惯了,以致于没有发现。

在中文中, 代替了 /-+,而 代替了 ABC256 就写做 二百五十六个 比较累赘,咱们一般把它省略了。

其实像日语、英语用的也一样是这种记数法,简洁、优雅。

美中不足的是,这种形式虽便于读写,却不便于计算。中国古人为算筹和算盘这类经典算具搭建起广阔的舞台,却没给笔算留出一席之地。想象一下,若是让你把这些汉字写在草稿纸上,列个竖式,你的心里必定很是别扭。

位值制记数法

公元5世纪,印度数学家阿耶波多(Aryabhata 476–550)创立了如今普遍使用的 位值制记数法(positional notation/place-value notation),该记数法使用的主要符号,是同为印度人发明的阿拉伯数字:0123456789

与符值相加记数法类比,位值制中的 123 代替的是 ABC,那 /-+ 呢?是 靠阿拉伯数字的位置来表示的。众所周知,最右位至关于 /,次右位至关于 -靠每一个位置上的数值来表示数字,故名位值制。

严谨的数学家用一种多项式高度归纳了位值制记数法的本质,在十进制中,这个多项式是这样的:

这是一个 n 位十进制数,ai 就是第 i 位上的数值。为便于直观理解,举个 1024 的例子吧:

因为咱们熟悉了十进制,这样费心费力的展开可能会让你以为可笑,但当咱们把它推广到其余进制时,这个多项式的价值就体现了出来。n 位 b 进制数的位值制表示:

1024 用二进制怎么表示?

所以,1024 的二进制写做 10000000000

除了最广泛的十进制和计算机中的二进制,常见的还有七进制(如 17 天)、十二进制(如 112 个月)、十六进制(如古代 116 两)、六十进制(如六十甲子)等等,只要有意义,任何进制均可觉得你所用。

为何使用二进制

至此,你对「二进制」或许再也不那么陌生,它仅仅是数制的一种而已。

可为何必定是二进制呢?使用人类习惯的十进制很差吗?

理由一:物理上易于实现

计算机依靠电力工做,这也就意味着须要将数字信号映射到电信号,实现这种映射最简单的方法是:

  • 0 - 没有电(0 V)
  • 1 - 有点(5 V)

二进制在技术上最容易实现。这是由于具备两种 稳定状态 的物理器件不少,如门电路的导通与截止、电压的高与低等,而它们刚好能够对应表示 “1” 和 “0” 这两个数码。假如采用十进制,那么就要制造具备 10稳定状态 的物理电路,而这是很是困难的。

理由二:机器可靠性高

为何使用更复杂的数字系统是一个问题?

假设咱们使用三元(3 位数字)数字系统涉及计算机,若是咱们具备从 0 V5 V 的电压,那么咱们能够进行如下的映射:

  • 0 - 0 V;
  • 1 - 2.5 V;
  • 2 - 5 V;

看起来合理吧?可是,想象一下,我以 2.5 V 的电压发送了一个数字。可是因为电路中的一些噪声,我在输出端获得 2.3 V 的电压,所以将其视为 0。结果是?

有人给我发送了 1,但我将其视为 0。数据丢失但是一个很是严重的问题。

使用二进制则可靠得多,因为电压的高和低、电流的有和无等都是一种 质的变化,两种物理状态稳定、分明,所以,二进制码传输的抗干扰能力强,鉴别信息的可靠性高。

为何计算机系统必须有时钟

创建数字系统的目的是 仅在某些时间点测试开/关(二进制)值,这使电线(或其余设备)有时间更换。这就是计算机系统有时钟的缘由。

时钟会周期性地进行信号的测量,图中所示的 T1 和 T2 就是能够测量信号的时间点。

时钟利用全部这些时间点来保持同步。更快的时钟意味着每秒能够对电线进行更屡次测试,而且整个系统运行得更快。2 GHz 处理器每秒检查二进制值 20 亿次。在这些时间之间,容许值改变并稳定下来。处理器芯片速度越快,每秒能够测试的次数就越多,每秒能够作出的决策就越多。

理由三:运算规则简单

数学推导已经证实,对 N 进制数进行算术求和或求积运算,其运算规则各有 N(N+1)/2 种。如采用十进制,则 N=10,就有 55 种求和或求积的运算规则;而采用二进制,则 N=2,仅有 3 种求和或求积的运算规则,以上面提到的加法为例:

0+0=0,0+1=1 (1+0=1),1+1=10

于是能够大大简化运算器等物理器件的设计。

理由四:逻辑判断方便

采用二进制后,仅有的两个符号 “1”“0” 正好能够与逻辑命题的两个值 “真” 和 “假” 相对应,可以方便地使用逻辑代数这一有力工具来分析和设计计算机的逻辑电路。

虽然在 1950 年代就造出了更加高效的三元计算机,但在效率和复杂度的取舍上,始终抵不过二进制。二进制仍然在当今世界中长期存在。

CPU 的实际工做方式简单演示

上面咱们了解到计算机以二进制的形式运行,它们只有两种状态:开(1)和关(0),为了执行二进制计算,咱们须要采用一种特殊的电子元器件,称为 「晶体管」。暂时咱们把它理解为一种开关吧,通电就打开,没电流经过就关闭。

利用「开关」搭建逻辑电路

咱们知道,给电灯通上电,它就会亮:

因而,结合上开关,咱们就能搭建出最基础的 与门或门

与门

该电路的逻辑是:只有当 A 和 B 同时开启时,LED 灯才会亮,也就是认为输出 1,咱们能够利用电信号来简单模拟一下:

A B Y
0 0 0
1 0 0
0 1 0
1 1 1

或门

该电路的逻辑是:当 A 或者 B 开启时,LED 灯就会亮,也就是认为输出 1,咱们能够利用电信号来简单模拟一下:

A B Y
0 0 0
1 0 1
0 1 1
1 1 1

其余门

相似地,咱们能够借助更多的电子元器件来创造出基础的 7 种逻辑门电路:

这里须要特别提一下 异或门,咱们须要先知道有一种电子元器件能够利用电气特性对 输入取反,也就是说输入 1 则输出 0,输入 0 则输出 1,那么咱们就能够 简单模拟 出异或门逻辑电路(实际会更复杂些,这里仅展现出异或的意思):

A'B' 分别表示 AB 开关的反值,从图中咱们很容易知道只有当 AB 只存在一个输入 1 时,整个电路才会输出 1

利用逻辑门制做简单加法器演示

OK,上面咱们了解到咱们可以利用 "开关" 来模拟逻辑的运算,咱们接下来试着还原一个简单的加法运算器是如何实现的:

仅需两个门,就能够完成基本的二进制加法运算。上图是利用 logic.ly 建立的半加法器,AB 至关于使咱们计算的两个数,最后一块至关因而咱们的数显芯片,它的功能是根据输入显示数字,从上到下的引脚(也就是图中输入的地方,一般咱们这样称呼)分别对应了 20=121=222=423=8 的输入,没有任何输入时显示为 0,若是 引脚 1(对应 20=1)像上图同样有输入,则显示 0 + 1 = 1

咱们来理解一下上方的电路:

  • 若是仅打开一个输入,但不一样时打开两个输入,则此处的 XOR 门(异或门)将打开,此时对应输入 引脚 1,显示 数字 1(相似于 1 + 0 和 0 + 1);
  • 若是两个输入均打开,则 AND 门(与门)将打开,此时对应输入 引脚 2,显示 数字 2(相似于 1 + 1);
  • 若是没有输入,则 AND 门和 XOR 门都保持关闭,此时显示 数字 0(相似于 0 + 0);

所以,若是两个都打开,则 XOR 保持关闭,而且 AND 门打开,得出正确的答案为 2

但这只是最基础的半加法运算器,不是太有用,由于它只能解决最简单的数学问题之一。但若是咱们把它们两个与另外一个输入链接,就会获得一个完整的加法器:

仔细思考几遍,你就会得知这个三个输入的加法器已经能够计算 3 个二进制数字的加法运算了,咱们如法炮制,能够经过链接更多的"进位"来使这个加法器可以运算更多的数,这固然也意味着这个计算链条更长。

大多数其余数学运算均可以加法完成。乘法只是重复加法,减法能够经过一些奇特的位反转来完成,而除法只是重复减法。而且,尽管全部现代计算机都具备基于硬件的解决方案以加快更复杂的操做,但从技术上讲,您可使用完整的加法器来完成所有操做。

一句话总结

编码伴随探索和学习新知的过程,若是愿意,咱们能从中获取不少相似于解出一道数学题的乐趣。

Part 3. 机器指令到高级语言 | 站在先驱巨人的肩膀

机器指令

咱们已经了解了 二进制和 CPU 的基本原理,知道了程序运行时,CPU 每秒数以亿次、十亿次、百亿次地震荡着时钟,同步执行着微小的 「电子操做」,例如:从内存读取一个字节的数据到 CPU 又或者判断字节中的某一位是 0 仍是 1

CPU 自己有一组 规定好的 能够执行的 「基本动做」(被称为 机器指令):

  1. 读取指令;2. 执行指令;3. 写寄存器;

这几乎就是 CPU 工做的所有了。 这些动做虽然每次只能执行一次,可是每秒能够执行数十亿次,这个数量级的「小操做」累加成为一个大的「有用的操做」。

处理器所作的一切都是基于这些微小的操做!幸运的是,咱们已经再也不须要了解这些操做的详细信息就能够编写和使用各种程序。诸如 Java 这一类的 「高级语言」目的 就是 将这些微小的电子操做组织成由人类可读的「程序语言」表示的大型有用单元

尽管机器语言有一些反人类,但至少咱们能够用它来来编写代码了,如:

00000001 00000010 00000001
00000100 00000100 00000000

彷佛看着这一段儿代码有点迷糊,而且 可读性太差了

如此你就会感知到 上个世纪 的程序员使用 打孔卡片

使用 纸带

甚至是 直接插拔线路 or 按下开关

是一件多么硬核的事情...

汇编语言

PU 的指令都是 二进制 的,这显然对于人类来讲是 不可读 的。为了解决二进制指令的可读性问题,工程师将那些指令写成了 八进制。二进制转八进制是垂手可得的,可是八进制的可读性也不行。

很天然地,最后仍是用文字表达,加法指令写成 ADD。内存地址也再也不直接引用,而是 用标签 表示。

这样的话,就多出一个步骤,要把这些文字指令翻译成二进制,这个步骤就称为 assembling,完成这个步骤的程序就叫作 assembler。它处理的文本,天然就叫作 aseembly code。标准化之后,称为 assembly language,缩写为 asm,中文译为 汇编语言

汇编语言演示

举个简单的例子,咱们须要计算:

(1 + 4) * 2 + 3

咱们按照 「后缀表示法」 进行一下转换:

1,4,+,2,*,3,+

咱们日常使用的方法是 「中缀表示法」,也就是把计算符号放中间,例如 1 + 3,后缀则是把符号放最后,例如 1, 3, +

这样作的好处是没有先乘除后加减的影响,也没有括号,直接运算就好了。(例如 1, 3, +,先把 13 保存起来碰到 + 知道是加法则直接相加)

OK,咱们从头开始使用汇编语言来编写一下程序,首先第一步:把 1 保存起来(放入寄存器):

MOV  1

以后是 4, +,那就直接加一下:

ADD 4

而后是 2, *,那就直接乘一下(SHL 是向左移动一位的意思,二进制中左移一个单位就至关于乘以 2,例如 01 表示 1,而 10 则表示 2):

SHL 0

最后是 3, +,再加一下:

ADD 3

完整程序以下:

MOV  1
ADD  4
SHL  0
ADD  3

这彷佛看起来比 00001111 这样的二进制要好上太多了!程序员们感动到落泪:

高级语言

摆脱了 二进制,咱们有了更可读的 汇编语言,但仍然十分繁琐和复杂,每一条汇编指令表明一个基本操做,例如:「从内存 x 位置获取一个数字并放入寄存器 A」、「将寄存器 A 中的数字添加到寄存器 B 的数字上」。这样的编程风格既费时又容易出错,而且一旦出错还很难发现。

例如,咱们来看一看 「1969 年阿波罗 11号登月计划」 用来 防止登月舱计算机耗尽自身资源 的 BAILOUT 代码:

POODOO    INHINT
    CA  Q
    TS  ALMCADR
 
    TC  BANKCALL
    CADR  VAC5STOR  # STORE ERASABLES FOR DEBUGGING PURPOSES.
 
    INDEX  ALMCADR
    CAF  0
ABORT2    TC  BORTENT
 
OCT77770  OCT  77770    # DONT MOVE
    CA  V37FLBIT  # IS AVERAGE G ON
    MASK  FLAGWRD7
    CCS  A
    TC  WHIMPER -1  # YES.  DONT DO POODOO.  DO BAILOUT.
 
    TC  DOWNFLAG
    ADRES  STATEFLG
 
    TC  DOWNFLAG
    ADRES  REINTFLG
 
    TC  DOWNFLAG
    ADRES  NODOFLAG
 
    TC  BANKCALL
    CADR  MR.KLEAN
    TC  WHIMPER

彷佛不太容易读的样子...

阿波罗登月计划的源代码在 Github 上已经公开,有兴趣的能够去下方连接膜拜一下(能够去感觉一下当时程序员的工程能力):

另外附一下当时代码的设计负责人 Margaret Heafield Hamilton(女程序员)和完成的堆起来跟人同样高的代码量:

第一个高级语言:FORTRAN

John Backus1950 年以一名科学程序员的身份加入 IBM 时,已经可使用诸如 ADD 之类的助记词代替数字代码来编写程序,也就是咱们的汇编语言。这使编程变得容易一些,可是即便是一个简单的程序也须要数十次操做,而且仍然很难找到错误。

巴克斯认为,应该有可能建立一种编程语言,使一系列计算能够用相似于数学符号的形式来表达。而后,使用特定的翻译程序(以今天的术语来讲是编译器)能够将其转换为计算机能够理解的数字代码。

Backus 在 1953 年向他的经理提出了这个想法。他获得了预算,并被鼓励雇用一个小团队来测试该想法的可行性。三年后,该团队发布了一本手册,其中描述了 IBM Mathematical Formula Translating System(简称 FORTRAN)。不久以后, IBM 向 IBM 704 的用户提供了第一个 FORTRAN 编译器。

FORTRAN 之父

Backus 和他的团队创造了世界上第一种高级编程语言。科学家和工程师将再也不须要将其程序编写为数字代码或冗长的助记符

FORTRAN 代码演示

下面演示计算并输出 8 * 6 的代码实例:

program VF0944
implicit none

integer a, b, c
a= 8
b= 6
c= a*b

print *, 'Hello World, a, b, c= ', a, b, c
end program VF0944

对比汇编代码,是否是看上去要清晰(人类可读)多了呢?

FORTRAN 的意义

FORTRAN 的问世在计算机史上具备划时代的意义,它使计算机语言从原始的低级汇编语言走出来,进入了更高的境界,使得 计算机语言再也不是计算机专家的专利,使广大的工程技术人员有了进行计算机编程的手段。

由此计算机更快地深刻到了社会之中,它在工业部门中初露头角,更是在火箭、导弹、人造地球卫星的设计中大显身手,所以有人称 FORTRAN 语言使计算机的工业应用成了可能,是推进第二次世界大战之后西方工业经济复苏和进入第二次工业革命的无形力量,是 "看不见的蒸汽机"。

一句话总结

计算机先驱们已经为咱们架设好了计算机的世界,站在先驱巨人们的肩膀,咱们现在很容易也能够看得更高和更远。

Part 4. 构建本身独有的程序(世界)

编码的乐趣有不少,把本身的想法动手实践就是其中一个。

例如网友玩儿游戏活动须要不停点鼠标,因而写了一个鼠标连点器:

例如给本身心爱的妹子写一个恋爱记念网站:

例如给 FlappyBird 加一个强化学习算法让它本身学习如何飞行:(图示已经能本身飞 4527 步了)

例如网友本身写的文言文语言:(使用文言文写代码)

// HelloWorld 程序演示
吾有一數。曰三。名之曰「甲」。
為是「甲」遍。
	吾有一言。曰「「問天地好在。」」。書之。
云云。

运行输出:

問天地好在。
問天地好在。
問天地好在。

一句话总结

咱们能够动手经过编程把咱们的不少想法付诸于实现 (前提是不断探索和学习),并在迎接挑战和最终实现的过程当中得到无限的乐趣。

小总结

整体而言,IT 是使人兴奋的。

素有「软件吞噬世界」的说法,咱们也正生活在计算机当道的世界。

而且编程并非每一个人都具有的技能,借助技术,一切皆有可能,而且如今互联网时代比以往都更有机会学习和建立「本身的世界」。

  • 本文已收录至个人 Github 程序员成长系列 【More Than Java】,学习,不止 Code,欢迎 star:https://github.com/wmyskxz/MoreThanJava
  • 我的公众号 :wmyskxz,我的独立域名博客:wmyskxz.com,坚持原创输出,下方扫码关注,2020,与您共同成长!

很是感谢各位人才能 看到这里,若是以为本篇文章写得不错,以为 「我没有三颗心脏」有点东西 的话,求点赞,求关注,求分享,求留言!

创做不易,各位的支持和承认,就是我创做的最大动力,咱们下篇文章见!

相关文章
相关标签/搜索