一种计算机专业都学什么可做10000000000次运算,他工作200秒可做几次运算?

&h2&前言&/h2&&p&2015年03月第一次编写这个答案,之后于2016年01月和2018年03月分别进行整体修改。只适合于入门,评论中的一些问题参见&a href=&https://www.zhihu.com/question//answer/#%E9%9B%86%E4%B8%AD%E5%9B%9E%E5%A4%8D& class=&internal&&集中回复&/a&。&/p&&h2&正文&/h2&&p&我觉得入门学习算法与数据结构时应包含三个部分:&/p&&ul&&li&选择一本合适的书。&/li&&li&编程实现和应用。&/li&&li&反复学习。&/li&&/ul&&h2&1. 选择一本合适的书&/h2&&p&十分推荐普林斯顿的这本橙书:&a href=&//link.zhihu.com/?target=https%3A//algs4.cs.princeton.edu/home/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&《算法 第四版》&/a&,是我认为最适合拿来入门的。在橙书中淡化了算法分析和证明,强调了实现和应用,并且通过一些有趣的习题对比显示了优秀的算法与数据结构在时间和空间上的高效。&/p&&p&橙书是使用 Java 进行代码实现,在第一章前两个小章节介绍了全书可能需要使用到的一些简单的 Java 语法,使得我们不会将过多的精力花费在编程语言的学习上。&/p&&p&并且普林斯顿在 &a href=&//link.zhihu.com/?target=https%3A//www.coursera.org/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Coursera&/a& 上也公开了两门对应课程:&a href=&//link.zhihu.com/?target=https%3A//www.coursera.org/learn/algorithms-part1& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Algorithms, Part I&/a& 和 &a href=&//link.zhihu.com/?target=https%3A//www.coursera.org/learn/algorithms-part2& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Algorightmsm, Part2&/a&。依次注册待开课后,&b&认真跟住&/b&课上内容(英文授课有字幕,如果已熟稔书本内容,并事先自己翻译了课件,英文听力不好也能理解),并&b&独立完成&/b& &i&Exercises(选择题)&/i&,&i&Programming Assignmengs(编程作业)&/i& 和
&i&Job Interview Questions(面试题)&/i&。&/p&&p&这2门 Coursera 公开课在知乎上也盛誉很多,在此不多赘述。不收费,同时也不给电子证书,一年开课几次,可随时加入。&/p&&h2&2. 编程实现和应用&/h2&&p&理解一个数据结构与编程实现其完整功能是完全不同的挑战。自己动手亲自实现一些基础数据结构(如排序,集合,图和字符串处理)的简化版 API 能够极大的提升对数据结构内部细节的理解。&/p&&p&&b&编写 API&/b&&/p&&p&我曾使用的一个较笨的方法是尝试默写书本中的实现。另一种较有成就感的方法是在如 &a href=&//link.zhihu.com/?target=https%3A//leetcode.com/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Leetcode&/a& 等 OJ (&a href=&//link.zhihu.com/?target=https%3A//baike.baidu.com/item/Online%2520Judge/Ffr%3Daladdin& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Online Judge&/a&) 上,选择一些简单的但会使用到上述基础数据结构的题目,自己实现那些需要使用到的数据结构,而不使用语言本身提供的,如 c++ 的 STL 或 Java 的 util。&/p&&p&&b&可视化帮助&/b&&/p&&p&同时,除了底层 coding,最好也从顶层宏观的去观察一种数据结构的各种操作。这里推荐一个动态可视化网站 &a href=&//link.zhihu.com/?target=https%3A//visualgo.net/en& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Visualgo&/a&。比如进入 Binary Heap(二叉堆),插入一个77,就可以看到整个堆的变化过程。可以通过左下角的按钮调慢演示过程。正刚刚在书本上学完二叉堆原理,可能也自己动手 code 实现了过程,那么再在网站上演示一下元素的各种操作过程,会带来一些更直观的印象。&/p&&figure&&img src=&https://pic4.zhimg.com/50/v2-26aa167b4ce712ed6386c_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1920& data-rawheight=&946& class=&origin_image zh-lightbox-thumb& width=&1920& data-original=&https://pic4.zhimg.com/50/v2-26aa167b4ce712ed6386c_r.jpg&&&/figure&&p&(在 Visualgo 上进行二叉堆操作的演示)&/p&&p&&b&尝试应用&/b&&/p&&ul&&li&认真且独立完成 Coursera 上《算法 第四版》的公开课作业。&/li&&li&对书本后的编程习题进行实现。&/li&&li&在 Leetcode 等 OJ 上解决相关数据结构的题目。&/li&&li&网上一些开源项目等。&/li&&/ul&&p&以上这些实践均能较快产生成就感。算法与数据结构学习不算轻松,能有一些及时的正反馈最好。&/p&&h2&3. 反复学习&/h2&&p&因为算法与数据结构所涵盖的知识较多,所以一本书里的内容可能都需要分几个阶段去学习,难免会遗忘之前的内容。我建议敏捷学习,尽量快的往后学习。如果一个知识点实在不懂,可以存疑,“不求甚解”,很多时候经过后面的学习,前面的一些内容就自然明了。然后反复学习。&/p&&p&除了基本的复习,还需要其他书籍进行一些补充和升级。推荐&a href=&//link.zhihu.com/?target=https%3A//mitpress.mit.edu/books/introduction-algorithms& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&《算法导论》&/a&。除显著加强算法分析的能力外,一些算法章节,如摊还分析,动态规划等是对《算法 第四版》较好的补充。其网上开放课程,中文有&a href=&//link.zhihu.com/?target=http%3A//open.163.com/special/opencourse/algorithms.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&网易公开课&/a&,英文有 &a href=&//link.zhihu.com/?target=https%3A//www.coursera.org/specializations/algorithms& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Coursera: Algorithms Specialization&/a&(可不要证书免费旁听)。&/p&&p&总之,要 &b&多做题善总结!&/b& 可以是 Online Judge 上的编程题,书后思考题,手上的编程项目或者面试题等等。&/p&&h2&补充&/h2&&ol&&li&因为我第一次编写这个答案时正看完&a href=&//link.zhihu.com/?target=https%3A//book.douban.com/subject/1139426/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&《数据结构与算法分析 - C 语言描述》&/a&,就在第一版回答中推荐了这本书。然而作为入门(个人意见)不如橙书详实,但它用 C 语言实现 ADT (抽象数据类型)的方法值得借鉴。&/li&&/ol&&h2&集中回复&/h2&&blockquote&&b&1. 问题是关于考研数据结构的学习,回答偏题!&/b&&br&确实。因时间久远我已经不记得原问题是什么,当初为什么在这个问题下写这个答案,归为某个被遗忘的历史原因吧。&br&&br&&b&2. 没用过 Java/C/C++ ,要先学编程语言&/b&&br&没必要。绝大部分书会使用某一特定语言进行代码实现,但都只用到该编程语言最基本的语法,凡有编程基础,都不需先从头学这门语言。&br&&br&&b&3. 英文不好,听不懂 Coursera 上的公开课。&/b&&br&可以先阅读中文书学习知识点,预先翻译网课课件,慢放视频,实在不行可暂停播放手动翻译字幕。刚开始这么做确实很吃力,但越往后越轻松,因为陌生的词汇就那么多,会一个少一个。&br&&br&&b&4. Coursera 需要翻墙?PC 上打不开。&/b&&br&PC 上访问不需要翻墙,可能是 DNS 污染的问题,参考&a href=&https://www.zhihu.com/question/& class=&internal&&知乎回答&/a&。&br&&br&&b&5. 《算法 第四版》课后题好多,又没有参考答案。&/b&&br&关于书后习题的讨论,参考&a href=&https://www.zhihu.com/question//answer/& class=&internal&&知乎回答&/a&。&/blockquote&
前言2015年03月第一次编写这个答案,之后于2016年01月和2018年03月分别进行整体修改。只适合于入门,评论中的一些问题参见。正文我觉得入门学习算法与数据结构时应包含三个部分:选择一本合适的书。编程实现和应用。反复学习。1. 选择一本合适的书…
&p&推荐神器,我已经帮助不下5个文科生转行CS学数据结构了,绝对的深入浅出,谁用谁知道:&br&&br&&a class=& wrap external& href=&//link.zhihu.com/?target=http%3A//www.comp.nus.edu.sg/%7Estevenha/visualization/index.html& target=&_blank& rel=&nofollow noreferrer&&VisuAlgo - visualising data structures and algorithms through animation&/a&&/p&
推荐神器,我已经帮助不下5个文科生转行CS学数据结构了,绝对的深入浅出,谁用谁知道:
&p&更新了一篇boltDB的模型和分析文档, 感兴趣的同学可以看看 &a href=&//link.zhihu.com/?target=https%3A//github.com/qw4990/blog/tree/master/database/boltDB& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&github.com/qw4990/blog/&/span&&span class=&invisible&&tree/master/database/boltDB&/span&&span class=&ellipsis&&&/span&&/a&&/p&&p&=====================&/p&&p&大概半年前, 我收到了这个问题的邀请.&/p&&p&现在我数据库完成, 我觉得我有底气回答这个问题了.&/p&&p&算是对我这将近一年工作的总结, 也当做是一些分享(zhuangX).&/p&&br&&br&&p&我大致说一下我从一开始做, 到完成我的作品, 大致经历了哪些阶段, 以做参考.&/p&&p&这里是我作品的github: &a href=&//link.zhihu.com/?target=https%3A//github.com/qw4990/NYADB2& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&GitHub - qw4990/NYADB2: NYADB2&/a&&/p&&br&&br&&p&PS: &/p&&p&因为大家对数据库的认知和了解都不同, 所以我的切入点必定无法满足所有人. &/p&&p&不过我想会关注这个问题的人, 大多应该都是用过简单的数据库功能, 感觉非常好奇, 想自己实现一个的人, 就同一年前的我一样.&/p&&br&&br&&p&下面我描述了我实现DB的各个阶段, 你可以在任意一个阶段停下, 然后实现它.&/p&&br&&br&&p&========================================================================================================================================&br&&/p&&br&&br&&p&&b&阶段1: 无事务, 单线程, 仅存在于内存的数据库.&/b&&/p&&br&&p&该状态下的数据库, 其实就是一个”索引结构”+”语法分析器”.&/p&&p&语法分析器分析SQL语句, 然后根据逻辑, 去执行相应的操作.&/p&&p&索引结构则是用来快速查询.&/p&&p&由于该版本仅存在于内存, 所以只要你会一些常见的索引算法, 即可完成, 可以称之为”简易内存数据库”.&/p&&br&&p&如你会B+树算法, 就可以实现一个B+树, Bt. &/p&&p&它实现了两个接口, Bt.Insert(key, value) -& void, Bt.Search(key) -& value.&/p&&p&再实现一个”语法分析器”.&/p&&p&如来了一条语句”Insert into student value (tony, 22, 123)”. &/p&&p&”语法分析器”分析该语句, 将value包裹一下, 选取一个该value的键值key.&/p&&p&然后调用 Bt.Insert(key, value). &/p&&p&之后执行”Read from student …” 其实也就是分析一下, 然后执行Bt.Search(key).&/p&&br&&p&该版本数据库完成.&/p&&br&&br&&p&========================================================================================================================================&br&&/p&&br&&br&&p&&b&阶段2: 无事务, 单线程, 不可靠的磁盘数据库&/b&&/p&&p&“磁盘”表示该版本将信息存放在磁盘上.&/p&&p&“不可靠”表示, 当数据库被非正常结束时, 不保证重启后, 数据库内容还会正确.&/p&&br&&br&&br&&p&&b&2.1: 思路描述&/b&&/p&&p&该版本也非常简单, 直接在版本1上修改.&/p&&p&可以这样, 如你索引结构的最小单位为Unit, (如B+树的每个节点就是一个Unit).&/p&&p&你将Unit编码成二进制数据, 然后为每个Unit, 在某个文件中, 分配一段固定的空间, 用来存放它.&/p&&p&于是, 当你需要Unit的信息是, 你从该文件的固定位置读入. &/p&&p&当修改Unit的信息后, 你再将它写到那个固定位置.&/p&&br&&p&如此一来, 数据就被存放于磁盘上了.&/p&&br&&br&&p&&b&2.2: 实现&/b&&/p&&p&这里为B+树提供一种最简单的思路.&/p&&br&&p&首先将索引数据和实际数据分别存放于两份文件, 称之为IndexFile, DB.&/p&&br&&p&B+树有一个BALANCE_NUMBER, 简称BN, 为定值, 那么一个B+树节点最多有2*BN个(key, value)的键值对.&/p&&p&我们将key固定为uint64, value固定为uint64类型.&/p&&p&那么一个B+树节点最多占用(8+8)*2*BN这么多byte, 将其表示为MAX_BYTES.&/p&&br&&p&于是, 就可以这样来编码B+树了.&/p&&p&规定根节点在IndexFile的位移为0.&/p&&p&每当创建新的节点时, 在IndexFile尾部, 追加MAX_BYTES大小的空间.&/p&&p&然后将该空间在IndexFile的位移, 作为这个新节点的”位置”, 用该空间存放新节点.&/p&&br&&p&于是, B+树内部节点的value就用来存放”对应子节点的位置”. &/p&&p&叶节点的value, 也被作为”位置”, 指向了该条记录在DB中的位移.&/p&&br&&br&&p&&b&2.3: 优化&/b&&/p&&p&上述实现会频繁的读写磁盘文件, 效率影响甚大.&/p&&br&&p&为了解决这个问题, 可以加入一个模块, 这个模块分页管理IndexFile文件, 并对其进行必要的缓存, 以加快访问效率.&/p&&br&&p&关于分页管理细节, 缓存算法, 不展开说了.&/p&&br&&br&&br&&p&&br&========================================================================================================================================&br&&/p&&br&&br&&p&&b&阶段3: 单事务, 单线程, 可靠的磁盘数据库&/b&&/p&&p&版本3在2的基础上, 同时支持了事务和数据库可靠性.&/p&&br&&br&&p&&b&3.1: 关于事务&/b&&/p&&p&首先需要了解事务的基本概念, 参考&&数据库系统概念&&.&/p&&br&&p&事务有ACID的性质, 由于现在是单线程版本, 所以不考虑其隔离性(I).&/p&&br&&p&对于ACD这几个性质, 通常配合一定的”日志机制”完成.&/p&&br&&p&于是需要去了解常见的”日志机制”.&/p&&p&这里推荐&&数据库系统概念&&日志恢复的那几章节.&/p&&br&&br&&p&&b&3.2: 实现&/b&&/p&&p&有了”日志机制”, 具体实现的时候还要考虑一些更加细节的东西.&/p&&br&&p&这里是Sqlite的一篇官文, 描述了一些错误会怎么发生, 应该对操作系统做什么样的假设.&/p&&p&不必了解该文档每个细节, 但是可以扩展下思路: &a href=&//link.zhihu.com/?target=http%3A//www.sqlite.org/howtocorrupt.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&How To Corrupt An SQLite Database File&/a&&/p&&br&&p&这里是Sqlite官方介绍怎么实现原子性的文档: &a href=&//link.zhihu.com/?target=http%3A//www3.sqlite.org/atomiccommit.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Atomic Commit In SQLite&/a&&/p&&p&同样不需要了解每个细节, 可以扩展下思路.&/p&&br&&br&&p&&b&3.3: 个人总结&/b&&/p&&p&通常, 利用设计好的日志机制来保证事务的ACD性质.&/p&&p&然后利用对操作系统的一些假设, 来保证关键信息的原子性修改, 如数据库的”Boot”信息等.&/p&&p&如在我自己的实现中, 我就假设了操作系统的”rename”是原子性的.&/p&&br&&br&&p&&br&========================================================================================================================================&br&&/p&&br&&br&&p&&b&阶段4: 多事务, 多线程, 可靠的数据库&/b&&/p&&p&前面三个阶段已经有一些内容了, 但是和多线程下的情况相比, 微不足道.&/p&&br&&br&&br&&br&&p&&b&4.1: 可串行化调度&/b&&/p&&p&首先需要了解操作冲突的概念, 可串行化调度, 以及解决该问题的”两段锁协议”等, 推荐&&数据库系统概念&&.&/p&&br&&p&两段锁协议会带来一个新的问题, 死锁.&/p&&br&&p&于是, 你还需要去了解解决死锁的一些办法.&/p&&br&&p&我使用的是有向图判环. &&数据库系统概念&&中有一定的介绍.&/p&&br&&br&&br&&br&&p&&b&4.2: 解决读写冲突&/b&&/p&&p&使用”两段锁”能够完成可串行化调度, 但是它会造成”读写阻塞”, 很影响数据库的效率.&/p&&br&&p&当然, 你也可以不解决该问题.&/p&&br&&p&不过我借鉴了Postgresql, 引用了MVCC(多版本并发控制)来解决该问题.&/p&&br&&p&MVCC的资料就大家自行搜索.&/p&&br&&p&总体思路大致是: 为每条数据维护多个版本, 如果事务1锁定了该条数据, 而事务2准备读取的话, 就返回给事务2更老的版本.&/p&&br&&br&&br&&br&&p&&b&4.3: 事务隔离度&/b&&/p&&p&还是得先了解隔离度的基本概念: &a href=&//link.zhihu.com/?target=http%3A//www.postgres.cn/docs/9.4/transaction-iso.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&事务隔离&/a&&/p&&br&&p&然后在MVCC的基础上, Postgresql通过维护各个版本对事务的可见性, 来实现了多种隔离度.&/p&&br&&p&关于Postgresql怎么实现MVCC, 也请大家自行搜索, 或者直接看我的模型中的VM模块, 我借鉴了此方法.&/p&&br&&br&&br&&br&&p&&b&4.4: 并发的索引&/b&&/p&&p&除了事务本身需要进行并发控制, 之前那些没考虑并发的模块, 也要加上并发支持.&/p&&br&&p&其中最重要的一个就是并发的索引结构.&/p&&br&&p&B+树本身是不支持并发访问的, 为了让他支持并发, 需要设计一些协议, 或者更改B+树算法来保证其支持并发.&/p&&br&&p&我借鉴了一份文档的办法, 引入了这份B+树并发访问协议: &a href=&//link.zhihu.com/?target=https%3A//qw4990.gitbooks.io/nyadb/content/chapter6.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Sixth Chapter&/a&&/p&&br&&p&解决了该问题.&/p&&br&&br&&br&&br&&p&&b&4.5: 总结&/b&&/p&&p&4.1到4.4大致说明了并发的情况下, 数据库会遇到哪些新的问题, 以及解决它们的办法.&/p&&br&&p&虽然每个小节都只有几句话, 但是坑挺深, 每个问题都有各种各样的解决办法, 我只说了我使用到的.&/p&&br&&p&但是, 比起单个解决这些问题, 最重要的, 是考虑怎么让它们组合起来使用也不会出错.&/p&&br&&p&在组合这些方法的过程中, 你需要对这些方法做调整, 其实也就是设计并组合你自己的模块, 这非常重要, 也非常有趣.&/p&&br&&p&如果想明白了上面各种方法怎么协同工作, 且发现不会引入新的问题, 那么可以把上面所有方法的总结抽象为一个完整”模型”了.&/p&&br&&p&而下一步就是将这个”模型”实现.&/p&&br&&br&&br&&p&&br&========================================================================================================================================&br&&/p&&br&&br&&p&&b&阶段5: 实现版本4&/b&&/p&&p&想清楚了模型, 那么开始实现它.&/p&&br&&br&&br&&p&&b&5.1: 准备&/b&&/p&&p&首先需要肯定的是将会在编程中用到并发, 需要去了解一些常见的并发概念, 问题, 以及解决方法.&/p&&br&&p&如临界区, 信号量, 锁, 读者写者问题, 哲学家就餐问题等概念.&/p&&br&&p&接着你需要选择一门并发支持较好的语言(我选的是Go).&/p&&br&&p&然后去学习该语言的一些并发编程技巧.&/p&&br&&br&&br&&br&&p&&b&5.2: 开始编程&/b&&/p&&p&这个过程就没什么可以多说的了, 就是考验编程功底.&/p&&br&&p&将模型抽象清楚, 然后开始写:) &/p&&br&&p&我前后的尝试过程大致为:&/p&&ol&&li&一开始尝试用c++写个单线程版本, 后面放弃了.&/li&&li&用java实现了一个单线程版本, 总共大概约1200行.&/li&&li&尝试用java实现多线程版本, 最后放弃了.&/li&&li&用Go实现了一个多线程版本, 最后代码加注释大致10000行.&/li&&li&重构了Go的多线程版本, 得到现在的版本, 注释加代码大概7500行.&/li&&/ol&&br&&p&整个过程是痛苦并快乐的, 毫无疑问非常锻炼编程和抽象能力.&/p&&br&&p&&br&========================================================================================================================================&br&&/p&&br&&p&&b&阶段6: &/b&测试&/p&&br&&br&&p&&b&6.1: 各模块测试&/b&&/p&&p&这里的测试包括分模块测试和整体测试.&/p&&br&&p&你设计的各个模块之间, 应该是可以通过指定一些&协议&来解耦的.&/p&&br&&p&于是模拟这些协议, 你的模块应该是可以单独被独立测试的.&/p&&br&&p&如模块A对模块B的访问遵循了协议C.&/p&&p&现在你想单独测试模块B, 那么可以编写一个MockA, 模拟A的操作, 并且遵守协议C.&/p&&p&这样讲B和MockA一起测试.&/p&&br&&br&&p&&b&6.2: 整体测试&/b&&/p&&p&其实我自己的DB在整体测试上做的是不够的.&/p&&br&&p&目前我针对一些特定功能, 做了一些手动的测试.&/p&&br&&p&关于更好的测试方法目前我也还在思考中.&/p&&br&&br&&br&&p&&br&========================================================================================================================================&/p&&br&&p&&b&其他问题:&/b&&/p&&br&&p&实实在在的实现一个数据库当然还有其他很多问题, 如Server与Client的交互方法, 制定自己的SQL文法, 怎么有效优雅的解析SQL语句, 数据库运行状态的监控, 对日志文件进行自动归档等.&/p&&br&&p&我上面描述的是”数据库引擎”需要解决的重点问题, 这些问题就略过了.&/p&&br&&p&这些问题都是可以被作为&甜点&, 在&主菜&完成后慢慢品尝的.&/p&&br&&p&所以分清楚哪些问题是重点, 哪些问题是可以之后慢慢解决的也很重要.&/p&&br&&p&总的来说, 只要你设计好了自己的&模型&, &模型&之外的问题, 几乎都可以被作为&甜点&了.&/p&&br&&br&&p&&br&========================================================================================================================================&br&&/p&&br&&p&&b&总结:&/b&&/p&&br&&p&数据库的功能点非常多, 选好要解决的问题, 然后去查找对应问题的解决办法. &/p&&p&接着将这些单个问题的解决办法, 组合成一个能正确工作的模型.&/p&&p&每个数据库都有自己的模型, 设计这个模型是数据库最好玩, 也是最难的地方, 这是&主菜&.&/p&&br&&p&将模型抽象好, 用合适的方法去将其实现, 这是难点二.&/p&&p&这个难点就没有多说的了, 就考验编程功底.&/p&&br&&p&最后就是对数据库进行测试, 以及不断的完善.&/p&&p&则是&甜点&了.&/p&&br&&p&所以数据库不管在理论, 还是工程上, 还是在考验人的耐心上, 真是都挺难啊哈哈= =.&/p&&br&&br&&p&&br&========================================================================================================================================&br&&/p&&br&&br&&p&&b&一些可能会用到的资料推荐:&/b&&/p&&br&&p&1.可以看一下简单的自动机实现, 用于分析语法.&/p&&br&&p&2.B+树算法, 常见的缓存算法等, 推荐看wiki.&/p&&br&&p&3.&&数据库系统概念&&, 这本书可以看看有关事务, 恢复, 锁的那几章, 以做基础概念.&/p&&br&&p&4.&&inside sqlite&&, 这本书介绍了sqlite的后端模型, 原书非常短小, 大概80到100页. &/p&&br&&p&5.http://&a href=&//link.zhihu.com/?target=http%3A//www.sqlite.org/howtocorrupt.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&www.sqlite.org/howtocorrupt.html&/a&, &a href=&//link.zhihu.com/?target=http%3A//www3.sqlite.org/atomiccommit.html%3A& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&www3.sqlite.org/atomicc&/span&&span class=&invisible&&ommit.html:&/span&&span class=&ellipsis&&&/span&&/a& 这两篇Sqlite官方文档, 当做开阔思路.&/p&&br&&p&6.&&SQLite Database System: Design and Implementation&&, 也是介绍Sqlite实现的书, 和&&inside sqlite&&有部分重复, 可以选看.&/p&&br&&p&7.MVCC的相关文档以及Postgresql的可见性逻辑, 请自行谷歌.&/p&&br&&p&8.然后, 就是我自己实现的数据库模型文档了: &a href=&//link.zhihu.com/?target=https%3A//www.gitbook.com/book/qw4990/nyadb/details& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://www.&/span&&span class=&visible&&gitbook.com/book/qw4990&/span&&span class=&invisible&&/nyadb/details&/span&&span class=&ellipsis&&&/span&&/a&&/p&&br&&p&9.最后, 最重要的还是自己思考. 遇到一个问题, 解决一个问题.&/p&&br&&br&&br&&p&&br&========================================================================================================================================&br&&/p&&br&&br&&p&本人很少上知乎, 虽然在知乎发了这篇文, 但还是鼓励大家多动手, 少上知乎. (会被和谐么?&/p&&br&&p&最后, 感谢一直给予我帮助的左老师:)&/p&
更新了一篇boltDB的模型和分析文档, 感兴趣的同学可以看看 =====================大概半年前, 我收到了这个问题的邀请.现在我数据库完成, 我觉得我有底气回答这个问题了.算是对我这将近一年工作的总结, 也当做是一些分享(zhuangX). 我…
1. 全都不是基于正统3D引擎的多边形绘制,而是基于少数特定情况的简化版光线跟踪算法&br&2. 只能渲染特定几种物体,并不能渲染通用物体。&br&3. 无资源或者少资源(基本靠生成),重复&br&4. 16位代码,COM格式的可执行(没有PE头,代码数据和栈都在一个段内,指针只有两字节)&br&5. 尽可能用汇编来写&br&&br&你自己花点时间也能做出来,&br&&br&具体解释一下:&br&&br&简化版的 raycasting,实现起来的代码量比通用的多边形绘制方法至少 N个量级。&br&&br&基本的光线跟踪,在 320x200 的解析度下,从摄像机中心射出 320x200条光线,屏幕上每个点对应一条光线,首先碰撞到的物体的位置颜色,就是屏幕上这个点的颜色:&br&&figure&&img src=&https://pic4.zhimg.com/50/cb536edb36d2c72820afdb043aa6b0c9_b.jpg& data-rawwidth=&300& data-rawheight=&200& class=&content_image& width=&300&&&/figure&可以描述为下面这段代码:&br&&div class=&highlight&&&pre&&code class=&language-cpp&&&span class=&k&&for&/span& &span class=&p&&(&/span&&span class=&kt&&int&/span& &span class=&n&&y&/span& &span class=&o&&=&/span& &span class=&mi&&0&/span&&span class=&p&&;&/span& &span class=&n&&y&/span& &span class=&o&&&&/span& &span class=&mi&&200&/span&&span class=&p&&;&/span& &span class=&n&&y&/span&&span class=&o&&++&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&k&&for&/span& &span class=&p&&(&/span&&span class=&kt&&int&/span& &span class=&n&&x&/span& &span class=&o&&=&/span& &span class=&mi&&0&/span&&span class=&p&&;&/span& &span class=&n&&x&/span& &span class=&o&&&&/span& &span class=&mi&&320&/span&&span class=&p&&;&/span& &span class=&n&&x&/span&&span class=&o&&++&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&n&&DWORD&/span& &span class=&n&&color&/span& &span class=&o&&=&/span& &span class=&n&&RayCasting&/span&&span class=&p&&(&/span&&span class=&n&&x&/span&&span class=&p&&,&/span& &span class=&n&&y&/span&&span class=&p&&);&/span&
&span class=&n&&DrawPixel&/span&&span class=&p&&(&/span&&span class=&n&&x&/span&&span class=&p&&,&/span& &span class=&n&&y&/span&&span class=&p&&,&/span& &span class=&n&&color&/span&&span class=&p&&);&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&/code&&/pre&&/div&&br&其中函数 RayCasting(x, y) 就是计算从视点开始穿过屏幕上 (x, y)这个点的射线。&br&&br&所谓简化版的光线跟踪,是只需要实现特定物体,以及针对特定条件,比如早年游戏里面用的最多的实时光线跟踪绘制地形高度图的(比如三角洲特种部队,xxx直升飞机):&br&&figure&&img src=&https://pic1.zhimg.com/50/715ec26d8f63778eaca69_b.jpg& data-rawwidth=&320& data-rawheight=&100& class=&content_image& width=&320&&&/figure&&br&比如云风 2002年写过的文章:&a href=&//link.zhihu.com/?target=http%3A//dev.gameres.com/Program/Visual/3D/Voxel.htm& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&3D地表生成及渲染 (VOXEL)&/a&&br&实现上述效果的地形渲染,只需要 200多行 C 代码&br&&br&使用标准三角形渲染这样的地形(软件渲染),代码少说也上千行了,使用标准的光线跟踪少说也要 500行左右。&br&&br&但是,我们情况比较特殊:&br&1. 只渲染地形(高度图)&br&2. 视角采用水平视角(可以象 doom一样左右转动,前后移动,但是不能偏头)&br&&br&光线跟踪的流程可以针对这种情况大大简化:&br&&figure&&img src=&https://pic4.zhimg.com/50/cb7aaab70d_b.jpg& data-rawwidth=&202& data-rawheight=&248& class=&content_image& width=&202&&&/figure&&br&(高度图,白色表示高的地方,黑色表示矮的地方)&br&&br&&figure&&img src=&https://pic2.zhimg.com/50/6ddeb91e0dc6a21d45c60cb_b.jpg& data-rawwidth=&308& data-rawheight=&232& class=&content_image& width=&308&&&/figure&&br&由于高度图的特殊性以及彩用水平视角,屏幕上同一列光线可以只算一条:&br&&figure&&img src=&https://pic1.zhimg.com/50/dcf8b2af0d921e0c1ba07_b.jpg& data-rawwidth=&614& data-rawheight=&324& class=&origin_image zh-lightbox-thumb& width=&614& data-original=&https://pic1.zhimg.com/50/dcf8b2af0d921e0c1ba07_r.jpg&&&/figure&没错,从屏幕最左边一列列的向右边绘制,每一列只需要先从最下方的光线寻找碰撞,找到碰撞以后,就逐步沿山体爬坡,计算出同一列其他光线的交点,这样的光线跟踪虽然效果看起来还行,最终代码写起来也就200行(C代码),用16位汇编紧凑点来写,256个字节未尝不可。&br&&br&嗯,好吧,其实云风是参考 flipcode 上的这篇文章:&br&&a href=&//link.zhihu.com/?target=http%3A//www.flipcode.com/archives/Realtime_Voxel_Landscape_Engines-Part_2_Rendering_the_Landscapes_Structure.shtml& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&flipcode - Realtime Voxel Landscape Engines&/a&&br&&br&有人用flash实现了一遍,直接可以在浏览器上看效果:&br&&a href=&//link.zhihu.com/?target=http%3A//www.unitzeroone.com/flex_2/voxel_landscape/& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://www.&/span&&span class=&visible&&unitzeroone.com/flex_2/&/span&&span class=&invisible&&voxel_landscape/&/span&&span class=&ellipsis&&&/span&&/a& (需翻墙)&br&&br&另一个著名的例子就是类《重返德军总部》,《DOOM》里面用到的光线追踪:&br&&figure&&img src=&https://pic1.zhimg.com/50/2c830fece0f5f9f798bbd893a913d8ee_b.jpg& data-rawwidth=&923& data-rawheight=&280& class=&origin_image zh-lightbox-thumb& width=&923& data-original=&https://pic1.zhimg.com/50/2c830fece0f5f9f798bbd893a913d8ee_r.jpg&&&/figure&这是 Javascript 实现的类 DOOM 引擎,只有 265行 js代码:&br&&a href=&//link.zhihu.com/?target=http%3A//www.playfuljs.com/a-first-person-engine-in-265-lines/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&A first-person engine in 265 lines&/a& (文章)&br&&br&这种地牢渲染情况也比较特殊:&br&1. 只渲染三种物体:墙壁,地面,天花板,&br&2. 同样采用水平视角&br&&br&先画地面和天花板:&br&也是从屏幕最下面投射一次性投射出一排光线出去,相交到地面(或天花板)上的某一行,&br&&figure&&img src=&https://pic2.zhimg.com/50/ece158b72d8ffd0a8e07802_b.jpg& data-rawwidth=&770& data-rawheight=&253& class=&origin_image zh-lightbox-thumb& width=&770& data-original=&https://pic2.zhimg.com/50/ece158b72d8ffd0a8e07802_r.jpg&&&/figure&从屏幕最下面那一行像素开始,计算那一排光线投射后相交于地面上的线段(x1,y1)-(x2,y2),代表代表地面上相交线段左右两边的端点,然后根据屏幕宽度缩放着绘制过去。&br&&br&接着绘制墙壁,从坐到有右判断交点就是了,一竖条一竖条的绘制:&br&&figure&&img src=&https://pic3.zhimg.com/50/1aaaee4bf460b3eed5210b_b.jpg& data-rawwidth=&771& data-rawheight=&236& class=&origin_image zh-lightbox-thumb& width=&771& data-original=&https://pic3.zhimg.com/50/1aaaee4bf460b3eed5210b_r.jpg&&&/figure&&br&&figure&&img src=&https://pic4.zhimg.com/50/3a196a8aff89dd5da2653_b.jpg& data-rawwidth=&726& data-rawheight=&260& class=&origin_image zh-lightbox-thumb& width=&726& data-original=&https://pic4.zhimg.com/50/3a196a8aff89dd5da2653_r.jpg&&&/figure&注意处理远小近大(除以z 来决定这一竖条墙壁的缩放比例)&br&&figure&&img src=&https://pic3.zhimg.com/50/8b85d9302ed4cbcd6a28a92ce982354e_b.jpg& data-rawwidth=&800& data-rawheight=&210& class=&origin_image zh-lightbox-thumb& width=&800& data-original=&https://pic3.zhimg.com/50/8b85d9302ed4cbcd6a28a92ce982354e_r.jpg&&&/figure&&br&早年不少地牢类 FPS游戏使用这个方法,实现起来也十分精简(javascript 才 265行)&br&&br&上面的几个例子,都是使用简化过的 raycasting 进行渲染:&br&1. 针对特定物体:地形,墙,地板 等&br&2. 采用水平视角(不能歪头)&br&&br&通过这种简化,光线路径计算十分的简单,不管是 C实现 或者 javascript/ flash 实现,代码基本可以控制在 200行内。&br&&br&来看第一个例子:&br&&figure&&img src=&https://pic3.zhimg.com/50/c4232bcdafe6d71cb665c_b.jpg& data-rawwidth=&320& data-rawheight=&200& class=&content_image& width=&320&&&/figure&明显的光线跟踪,只需要实现对一种特定的数学曲线/面的碰撞检测即可,颜色使用黄色,用交点的法向确定下明暗即可,效果十分平滑。&br&&br&然而,代码尺寸限制,它只能绘制这种数学曲线/面,并不能绘制其他形状的东西,所以并不能称为引擎。&br&&br&来看另一个例子:&br&&figure&&img src=&https://pic1.zhimg.com/50/d17eaa7abcbd9_b.jpg& data-rawwidth=&400& data-rawheight=&250& class=&content_image& width=&400&&&/figure&这个墙面只有两种类型(横的或者竖的),由于性能可以不用考虑太多,&br&可以比 doom的例子更简化一点,只对三种平面求焦点:&br&1. 地面或者天花板(z=-1,z=1)&br&2. 横墙:x坐标不变&br&3. 竖墙:y坐标不变&br&&br&算起来应该也很快,C实现的代码量有可能控制在150行左右。&br&&br&接下来是代码压缩了,选择 .COM的可执行格式,它没有 PE头,纯代码+数据,同时SP, ES, DS, CS 等四个段寄存器都是指向同一个数据段,所有数据都用 16位 near 指针访问(2字节)。&br&&br&最后手工重构成汇编版本(C编译器产生的代码实在太庞大了),如果有资源,用256色(8位)或者16色(4位), 并且使用 RLE压缩(解压代码很短),或者代码动态生成资源。&br&&br&我以前也用纯汇编实现过一个 1KB 左右的完整空战游戏,16位的手写汇编,100字节就能做好多事情了,按照上面的简化版 raycasting ,逻辑比空战游戏简单不少。&br&&br&通过不断的简化绘制模型,增加限制,以及不断的代码优化,&br&256个字节内实现题主图中的几个 demo应该是可以的。&br&&br&相关阅读:&br&&br&&a href=&https://www.zhihu.com/question//answer/& class=&internal&&计算机底层是如何访问显卡的? - 韦易笑的回答&/a&&br&&br&&a href=&https://www.zhihu.com/question//answer/& class=&internal&&想用C++实现一个软件渲染器,类似DX和OpenGL,除了《3D游戏编程大师技巧》,或者什么网站推荐? - 韦易笑的回答&/a&&br&&br&--
1. 全都不是基于正统3D引擎的多边形绘制,而是基于少数特定情况的简化版光线跟踪算法 2. 只能渲染特定几种物体,并不能渲染通用物体。 3. 无资源或者少资源(基本靠生成),重复 4. 16位代码,COM格式的可执行(没有PE头,代码数据和栈都在一个段内,指针只…
&p&答案定位:&br&既不是儿童级别的读物,也不涉及高深晦涩和非常专业的词句。该答案的目的是让有初中文凭的人读懂。 &/p&&p&&br&&/p&&p&&i&前前言:&/i&&/p&&p&所有读了这个答案但是有不懂的地方的朋友,恳请你们能告诉我哪里不明白,我会尝试用更通俗的话来阐述以帮助更多的朋友。谢谢!&/p&&p&&br&&/p&&p&&br&&/p&&p&&i&前言:&/i&&br&你需要有一定的电学知识,然后就可以去看模拟电路和数字电路相关的书籍了,了解完这两个东西后你就能基本明白计算机是怎么运作起来的了。这里只做简单回答。简单回答的意思是说,这个回答旨在&b&让完全没有基础的人从理念上了解计算机如何运作----针对这一原则,答主会一切围绕通俗易懂来展开,因此在某些学术细节上或许有错。&/b&&/p&&p&&i&读懂此答案需要具备的能力:&/i&&br&初中电学和数学知识 + 二进制的基本知识。&/p&&p&对于掌握了初中数学知识的朋友来说,大致了解二进制是很简单的,在这里做个简单介绍:&/p&&p&我们知道十进制是最常见的数制,它有十个数字0-9。二进制也同理,只不过二进制是两个数字。因此十进制里的“逢十进一”在二进制中变成了“逢二进一”。&/p&&p&十进制数数:1 2 3 4 5 6 7 8 9 10 11 12 ...&/p&&p&二进制数数:&a href=&tel:1%100%&&1 10 11 100 101 110&/a& 111
...&/p&&p&&br&&/p&&p&&br&&/p&&p&&br&&/p&&p&&i&正文:&/i&&/p&&p&1)半导体的发现。人类有一天被上帝丢下来的硅不小心砸到了脑袋,于是乎发现了半导体。用半导体材料可以制成&b&二极管。&/b&&/p&&p&二极管的原理:给半导体材料里掺入某种元素后,半导体会这样:&b&我讨厌电子&/b&;而给半导体掺入另外一种元素后,半导体会这样:&b&我喜欢电子&/b&。我们把一个讨厌电子的半导体和一个喜欢电子的半导体放在一起的时候,在它们之间就会形成一个电子趋向的力量(半导体毕竟不是导体,半导体的原子核对电子的束缚力是足够大的,因此虽然有趋向,但不足以让一侧的电子跑到另一侧 --- 这也就是为什么它叫做“半导体”),这就是一个二极管了。当二极管外部有电流通过的时候,如果外部电流内的电子的运动方向顺从了其内部的这种电子的趋向,则这个二极管可以视为接通的导线;而如果外部电流的电子运动方向和二极管内部的电子方向相反的时候,外部电流就无法通过这个二极管(除非加了很高的反向电压 ----- 这样就会将二极管&b&击穿&/b& ---- 当然我们在使用二极管时不会让它被击穿因此这里无需考虑这种情况),此时这个二极管可以视为断路。所以在二极管的电路里,根据二极管两端的电压的高低的不同,就能测出某些电阻两端的电压有不同的数值:高或者低(具体看下面的4)。&/p&&p&2)数学上有二进制:0和1。由于只有两个数字,因此恰好可以和上面的高低电压一一对应起来。比如我们可以规定:1表示高电压0表示低电压。&/p&&p&3)就像四则运算中的加减乘除一样,对于二进制我们有配套的逻辑运算:与、或、非。&/p&&p&与:&/p&&p&0与0=0&/p&&p&1与0=0&/p&&p&0与1=0&/p&&p&1与1=1&/p&&p&一句话描述:“只要有0结果就是0”。&/p&&p&或:&/p&&p&0或0=0&/p&&p&1或0=1&/p&&p&0或1=1&/p&&p&1或1=1&/p&&p&一句话描述:“只要有1结果就是1”。&/p&&p&非:&/p&&p&非0=1&/p&&p&非1=0&/p&&p&还有其他逻辑运算比如同或、异或等就不一一列举了;总之基础的逻辑运算就这三个。&/p&&p&4)把123联系起来,人类做出了:与门电路、或门电路、非门电路、异或电路等。&/p&&figure&&img src=&https://pic4.zhimg.com/50/28701cadcf8f26c39b3fe6c_b.jpg& data-rawwidth=&192& data-rawheight=&158& data-caption=&& data-size=&normal& class=&content_image& width=&192&&&/figure&&p&&br&&/p&&p&&i&注:&/i&&/p&&p&&i&上图中最上面的唯一一个没有被字母标记的结点在这里记为:C&/i&&/p&&p&&i&A、B和C都可以加上一定的电压;Y为测量端;DA与DB为二极管;C下面的矩形为电阻。&/i&&/p&&p&&br&&/p&&p&这是一个&b&与门电路&/b&,有初中电学知识就应该可以看懂。大概很简单地解释下(&b&其实不太对但是不影响你从原理上理解&/b&):&/p&&p&当A和B中任意一端是0V(可以理解为接地)而C端有一定的电压时(中学生理解方式:用导线将AB两点连接在一起后再连接到直流电源的负极,C点接正极),测量Y端电压(Y与大地间的电压或者说Y与0间的电压)几乎是0V。这是因为AB中&b&至少有一个&/b&是0V且二极管的方向是那个样子的,所以电流从C端流入、通过那个电阻后从0V那里流入大地/回到负极了,因此此时测量Y端电压等于在测量一个导通的电路中的一段导线上的电压,所以很显然几乎是0V。而如果AB端电压&b&都&/b&比较高(高于C端的电压但是没有到击穿的地步)的时候(中学生理解方式:用导线将AB两点连接在一起后再连接到直流电源的正极,C点接负极),两个二极管都等效于断路状态,电流试图从AB端流向右边(因为AB端电压高于C端电压因此电流的&b&趋向&/b&是从AB流向C)但是流不过去,所以此时测量Y端电压的时候就不是0V了而是有一定的数值。&/p&&p&因此,在这个电路中,只有当AB两端同时有高电压时,Y端才有电压(大于0V);AB中只要有一个是0V,Y端就是0V。当我们把AB两端视为输入Y端视为输出时,就可以得到和上面的“与运算”相对应的结果(设高电压=1 低电压=0):只有输入都是1的时候输出才是1,其他时候都是0。这就是一个与门电路。同理,也有类似的或门电路等等。&/p&&p&5)有了这些门,就可以做半加器了,有了半加器就能做全加器,它的作用是实现加法。同理,可以实现四则运算了(如何用这些门实现四则运算,这里不细说,否则就违背了“通俗易懂”的原则。但这样的跨度有点大,因此后面的BONUS里有介绍这部分内容)。到了这里,理论上只要我给你相关的材料,你就可以做出一个有一定功能的电路了。比如你可以做一个:输入三个数字,把前两个数字相加的结果乘以第三个数字然后输出结果。&/p&&p&比如,你输入“高低低高”给一个电路,然后这个电路给你输出“高低高低”。如果我们之前已经规定了高电压表示1、低电压表示0,即:1001为输入,1010为输出,显然,这就是做了一个加1的运算。&/p&&p&当然,由于你电路里的所有门电路都是盯死在线路板上的,所以你的这个电路永远只能做这一件事。然后你就可以做一个专门卖这种功能电路板的&b&硬件生产商&/b&了。像计算机里的那些固定在硬件上的指令,就是这么来的。所谓硬件上的那些指令,就是:你输入某些数字,硬件就做相关运算,然后输出结果。&/p&&p&很多朋友会在这里产生一个困惑(这个困惑甚至困扰着很多计算机专业的学生):你说用1表示高电压0表示低电压,那我怎么告诉电路这里是高电压或者低电压、电路又是怎么告诉我那里是高电压或者低电压呢?&/p&&p&&b&本质上,这个问题是在问:电路和人如何交流,或者说是在问电路的输入输出设备是什么。&/b&&/p&&p&&b&到目前为止,我们所需要用到的输入输出设备其实非常简单:输入设备就是一个个的开关 --- 开关接通则给电路输入高电压开关断开则给电路输入低电压;输出设备则是一个个的发光二极管或者简单理解为“灯泡” --- “灯泡”亮则表示电路输出了高电压“灯泡”不亮则表示电路输出了低电压。有了这样的输入输出设备,你就可以这样做了:通过控制一系列开关的状态,给电路输入高电压和低电压(即0和1);而后通过观察一系列“灯泡”的状态,来得到电路输出的结果。&/b&&/p&&p&6)逻辑完备性。这个世界中的万事万物都可以用三种顺序来表示出来:顺序、选择和循环。完备的意思就是说某个理论系统可以涵盖所有的情况,没有例外。&/p&&p&&b&&i&注:以下两个斜杠后面的部分属于注释,负责解释说明本行做了什么。&/i&&/b&&/p&&p&&br&&/p&&p&&b&顺序&/b&:从第一行到第二行再从第二行到第三行......(就像你看文章一样,一行一行地看)&/p&&div class=&highlight&&&pre&&code class=&language-text&&第一行:a = 1
// 告诉计算机:有一个值的名字是a,它的大小是1
第二行:b = 2
第三行:计算并显示(a + b)
// 逐行执行:第一行 ---& 第二行 ---& 第三行......
&/code&&/pre&&/div&&p&&b&选择&/b&:如果某个条件满足(比如x&y)就到第p行;如果不满足(比如x&=y)就到第q行&/p&&div class=&highlight&&&pre&&code class=&language-text&&第一行:a = 1
第二行:b = 用户输入
第三行:如果(a & b)
第四行:显示(用户输入小于a)
第五行:如果(a & b)
第六行:显示(用户输入大于a)
第七行:如果(a = b)
// 注意这里的等于号和第一行的等于号作用不同,这里是在判断a与b是否相等
第八行:显示(用户输入等于a)
// 还是逐行执行,但第四行、第六行和第八行中只有一行会被执行
&/code&&/pre&&/div&&p&&b&循环&/b&:如果某个条件不满足/满足(比如a&x)就到第p行,什么时候该条件满足/不满足了(比如a&=x)了就到第q行&/p&&div class=&highlight&&&pre&&code class=&language-text&&第一行:a = 0
第二行:b = 10
第三行:语句标签(label): c = a, a = c + 1
// 把c设置成a
然后把a设置成c+1
第四行:如果(a & b)
第五行:执行标签:label
// 跳到被label标记的那一行去执行,也就是第三行
第六行:显示(a)
// 还是逐行执行,但从第三行到第五行会不断反复执行:第三行 ---& 第四行 ---& 第五行 ---& 第三行......直至a不再小于b --- 即第四行的条件不满足了,就会执行第六行
&/code&&/pre&&/div&&p&&br&&/p&&p&用这三个可以表示世间万物。&br&比如:你上楼梯回家:&br&a---打开楼门,面前出现一个10个台阶的楼梯&br&b---循环做登楼梯的动作直到做了10次&br&c---如果面对的是你家,开门,到e;如果不是,向右转&br&d---如果到家了,到e;否则,到c&br&e---结束&br&7)图灵机。图灵机简单来说就是一个能&b&接受信息、处理信息和发出信息&/b&的虚构的机器。世间万物皆为图灵机。&br&比如,一个杯子放在一张桌子上:&br&输入:杯子&br&图灵机:桌子&br&输出:支持杯子或者说杯子没有掉下去&br&再比如,我对你说谢谢你回复我说不客气:&br&输入:谢谢&br&图灵机:你&br&输出:不客气&br&再比如6中的那个回家的例子:&br&输入:十个台阶的楼梯&br&图灵机:你&br&输出:重复十次登楼梯动作&br&当然,你这个图灵机在对信息的处理上远远比一张桌子要复杂得多:&br&如果 (十个台阶上面是你家 而且 你面对着台阶)&br&那么 (循环十次登楼梯动作)&br&当然,你不会是如此简单的一个图灵机。你还会这样:&br&在登楼梯过程中,如果有人通过你的耳朵给你输入:儿子别回家了,咱们到外面吃饭。&br&你这个图灵机就会立刻优先对这个新的输入进行处理而会将登楼梯的动作挂起(挂起的意思就是暂时不执行)&br&你会这样:&br&如果(声音是你爸或者你妈的)&br&那么(转身下楼梯)&br&否则 // 就是说声音不是你爸也不是你妈的&br&那么(唤醒刚才挂起的登楼梯的动作继续做)&/p&&p&回到家后,你这个图灵机会从你大脑里调出晚上要做的事情:写作业、看电视、睡觉&br&然后你会给这些任务排列一个优先级:比如写作业是1,看电视是2,睡觉是3。(坏孩子的任务优先序列可能是:看电视1,写作业2,睡觉3---小朋友们不要学哟)&br&你会根据哪个优先级更高来选择先做哪一个。&br&当然,远没有这么简单。比如:&br&如果(你正在做1 而且 时间已经12点了)&br&那么 (你决定停止1,直接做3,同时准备好明天给你们老师的输出 --- 跟他解释你为什么没写完作业)&br&......&br&......&br&......&br&所以人是一个非常非常非常非常复杂的图灵机。由于现在的5那里的硬件落后得和渣一样,所以人类目前根本无法用电路去模拟一个真人 。即使硬件发达到可以模拟真人了,那么依然也只是&b&模拟&/b&。人类最大的本领:学习,只靠发达的硬件还是无法做到。所以人类到底能不能真的用电路去实现一个真正的人类的大脑,这是一个悬而未决的问题,有的人认为可以,有的认为不可以。&br&&b&6+7:这个宇宙中的一切,都可以抽象成图灵机;这个世界上的所有事件,都可以用那三种逻辑来表示。&/b& &b&而用上面的5中的内容,可以在电路上实现6+7。只要电路的速度越来越快,我们就能实现越来越复杂的6+7。&/b& &b&图灵机,只是一个概念上的虚拟的机器。而人类可以通过各种手段去实现各式各样的图灵机:人类制造的机器,是图灵机;人类盖的楼房,是图灵机;哪怕人类生了一个婴儿,那个婴儿也是一个图灵机。计算机,只是众多图灵机中的一种。只要一个图灵机具备了6中所说的三种顺序的逻辑能力,那么这个图灵机理论上来说就可以模拟宇宙万物了。&/b&&br&比如在5)那里的那个做加1运算的“东西”-----其实那就是一台计算机。只不过它的输入是一个个的开关,而不是键盘和鼠标;它的输出是一个发光二极管闪了几下,而不是显示器和打印机。一个遥控器、一个手机、一个红白机,都是计算机、都是图灵机。&br&8)在半导体的基础上,如果加入一些其他化学元素(具体请去看模拟电路的书),就可以让半导体的状态变得“可擦除”和“可记忆”:比如上次这里是断路半导体状态、现在我可以改成连通的。我给一个电路板接通电路,然后给它某些输入、改变了里面的某些半导体的状态,然后断开电路,由于这种半导体是可记忆的,所以它里面的每个门电路都是你断电之前的状态,下次再接上电源的时候,就能读出上次的状态---这样就可以存储数据了。&br&9)振荡器。高中物理会学振荡回路。就是电磁一直相互转化而形成振荡,就和广播的道理一样。振荡的频率是固定的,比如每秒震荡100次,每振荡一次,就发射出一个电压信号。然后cpu每接收到一次电压信号,就去读一条指令(看6,类似这样:如果收到了电压信号,则执行***。当然还要有外来的用户输入,比如如果用户输入了1,同时接收到了电压信号,则执行a;如果没有用户输入,则执行b;如果用户第一次输入0第二次输入1,则执行c......)-----指令就是根据5那里被硬件生产商固定在硬件里的半导体的通断状态。一般你买电脑的时候都有个内存频率,单位都是MHz,表示一秒钟这个内存里的振荡器可以发送多少百万次信号。&br&到了这里,你就可以做出一个能处理四则运算和拉丁字母(拉丁字母可以和数字一一对应起来)的电路板了。&br&10)卷积定理+(离散)傅立叶变换+采样。大学数学基础课会学傅立叶变换,数学专业的某个方向会学卷积定理。你不需要知道它们是什么东西,你只需要这三个东西合起来能做这样一件事:&br&&b&真实世界的信息转换成连续信号、连续信号转换成数字信号。&/b&&br&虽然我们&b&永远不能&/b&把真实世界的信息&b&零误差地&/b&转换为数字信号,但是可以无限逼近。由于&b&人类太弱了感官系统太不敏感了&/b&,所以只要差不多逼近一点人是根本察觉不出来的。世界上有无数种红色,但计算机只要提供256种红色,人就以为能表示所有的红色了。&br&自此,你就可以做一个能处理数字、文字、声音和图像的机器了。&/p&&p&简单来说,只要能被转化成数字的信号,就都可以被计算机处理。&/p&&p&比如我们要处理256种颜色,那么我们只要把这些数字和1-256这些数字一一对应起来,那么当计算机要处理第一种颜色时,它只需要对数字1进行处理即可;当计算机处理完毕后,我们再把处理后的数字转换回它对应的颜色即可。这个过程就像是电话的原理:声波转换成电磁信号电磁信号最后又转换回声波。&br&11)荧光物质可以在受到不同能量的电子的轰击下发出不同的颜色,根据三原色原理,我们可以通过对电子加压的控制达到显示不同颜色的目的---------------------显示器。&br&12)键盘底下有一张导电的纸,你按下某个键,就等于接通了某些电路,就有一个独一无二的输出,你只要事先规定好哪种输出对应哪个键,主机就能够知道你按下了某个键了。比如规定“高低高高低低高高低”是K,那么主机只要从键盘那里接收到了&a href=&tel:&&&/a&就知道用户按下了K。&br&鼠标:鼠标下面的光源发射器会向桌子发光,还有个光的接收器。当你移动鼠标时,接收器可以感知到发射器发出的光反射回来时的入射角和方向的不同变化,然后就可以以不同电信号的方式告诉主机鼠标在向着那个方向移动;鼠标点击的原理和键盘类似,不再赘述。&/p&&p&&br&&/p&&p&把制作上面所有物件的材料都买齐了,然后你就能自己攒一个计算机出来了.............Good luck!&/p&&p&&br&&/p&&p&&br&&/p&&p&====================================================================&br&&b&上面说的这些其实非常粗浅,想知道完备的系统的知识请在上大学时报考计算机或通信专业:&/b& &b&通信就是把信息从自然界里捕捉到然后再转化成易处理的信息然后再通过各种方法传输最后到了信息处理的终端:计算机 这里。计算机处理信息后再把信息通过各种各样的方式传递出来。&/b& &/p&&p&&br&&/p&&p&&br&&/p&&p&&br&&/p&&p&&br&&/p&&p&&br&&/p&&p&=========================== BONUS ==========================&/p&&p&关于6:逻辑完备性。&/p&&p&如上所述,逻辑的完备性靠三种逻辑顺序实现:顺序、选择和循环。&/p&&p&用这三种逻辑顺序可以解决问题,比如上面7中的“回家”。这里再举一例:&/p&&p&计算从1到100的所有奇数的和。&/p&&div class=&highlight&&&pre&&code class=&language-text&&a = 1
result = 0
语句标签(label):
如果(a & 100)
那么(执行label2)
如果(a除以2的余数不等于0)
// 说明a是奇数
那么(result = result + a)
// 把result和a相加的结果赋值给result
执行标签:label
语句标签(label2):显示(result)
&/code&&/pre&&/div&&p&上面这个例子中把三种逻辑顺序已经都涉及到了。&/p&&p&依照这三种逻辑来描述世间的一切问题,可以把问题分为三类:&/p&&p&1)不可解决的问题。&/p&&p&虽然前面说了,用这三种逻辑顺序可以&u&表示&/u&一切事物但是&b&这并不意味着可以&u&解决&/u&一切问题&/b&。&/p&&p&举个例子:&/p&&p&显示自己本身的所有代码。&/p&&p&什么意思呢?就是说你写一段程序,这段程序要把自己所有的代码都显示出来。&/p&&p&乍一看觉得这很简单啊,但其实你连一行都显示不了。&/p&&p&比如有这样一个程序,就一行:&/p&&div class=&highlight&&&pre&&code class=&language-text&&显示(100)
&/code&&/pre&&/div&&p&这个程序就做一件事情:显示数字100。&/p&&p&问题来了,你如何把“显示(100)”这两个汉字一组括号和一个数字100显示出来呢?&/p&&p&似乎应该这样:&/p&&div class=&highlight&&&pre&&code class=&language-text&&显示(显示(100))
&/code&&/pre&&/div&&p&但是其实当你这样做的时候,你已经改变了程序本身,现在的程序为两个“显示”两组括号和一个100,而你运行程序后只能显示一个“显示”一组括号和一个100,很显然你并没有把这个程序全部显示出来。&/p&&p&类似这样的问题,就是计算机无法解决的问题。(有兴趣的朋友可自行百度:停机问题)&/p&&p&&br&&/p&&p&2)能够在人类可以容忍的限度内解决的问题。&br&比如上面的那个“计算1到100内的奇数的和”的问题就是这类问题。解决这类问题所需要的时间的变化是&b&线性变化&/b&的。即:“计算1到1000内的奇数的和”所需要的时间是“计算1到100内的奇数的和”的10倍。也就是说问题扩大多少,解决问题所需要的时间就&b&线性地&/b&扩大多少。&/p&&p&&br&&/p&&p&3)无法在人类可以容忍的限度内解决的问题。&br&这类问题是计算机或者说用这三种逻辑顺序可以解决的、但是所需要的时间是人类无法容忍的。&br&比如“背包问题”:&br&一个小偷去博物馆偷东西。博物馆内有3件物品。&br&第一件物品的重量为3, 价值为4;&br&第一件物品的重量为2, 价值为3;&br&第一件物品的重量为4, 价值为5;&br&小偷的背包最多可以承受的重量为7。请问:应该如何拿物品,可以让背包里的物品总价值最大。&br&这个问题似乎非常简单,你在稍微比较后就会得出结论:拿第一件和第三件物品。&br&但是,如果我们扩大一下问题:如果有6件物品、背包可以承受的重量也提高一些,应该怎么拿?&br&这个时候如果让计算机去解决这个问题,我们就会发现当问题的规模扩大1倍后,计算机所需要的时间却扩大了远不止1倍 ----- 即&b&解决问题所需时间不再是线性变化了。&/b&&br&就拿这个问题来说,如果物品数量超过12个(如果我没记错就是12个,反正这个数字很小),那么计算机要想解决这个问题所需要的时间就已经超过了100年。&/p&&p&&br&&/p&&p&&br&&/p&&p&上面的第三类问题,是今天人类在数学和计算机领域的难题,如果大家有兴趣可以了解一下。(自行百度:P问题 NP问题 NPC问题)&/p&&p&&br&&/p&&p&&br&&/p&&p&&br&&/p&&p&&br&&/p&&p&======================== BONUS2 =========================&/p&&p&关于8:存储器类型。&/p&&p&8中所涉及的存储器,其实只是硬盘、U盘等存储器的原理。这类存储器的特点是:存放在其中的数据&b&断电后仍然存在&/b&,但读数据和写数据都&b&非常慢&/b&。&/p&&p&而计算机在运行时会产生很多临时的数据,这些数据只是为当下正在运行的一些程序而服务的,使用计算机的用户并不关心这些数据。相应程序结束或者计算机断电后这些数据就没有存在的必要了。&/p&&p&比如有如下程序:&/p&&div class=&highlight&&&pre&&code class=&language-text&&sum = 1 + 2
&/code&&/pre&&/div&&p&执行这一行的时候,计算机先计算等号右面的值 ---- 结果是3,然后把3存放在一个临时的地方,最后再把这个临时地方里的数值3赋值给sum。(为什么不能直接赋值给sum而要经过一个“临时的地方”:等号右侧的计算,必须在计算机内专门做计算工作的芯片 --- 也就是CPU内完成,完成计算后的结果只能保存在CPU的临时存储空间里,然后sum才能拿到这个值)这里的这个“临时存放的地方”,它只是为这个程序而暂时服务一下,过后就不再需要它了。于此同时,我们需要它的读写数据的速度要足够快。如果我们用硬盘来“临时存放这个3”,那么计算机执行这么一行代码也得需要好几秒因为计算机读写硬盘的速度是非常慢的。&/p&&p&因此我们还需要一种存储器:&b&断电后数据不需要存在,但是读写数据的速度要够快&/b&。&br&这种存储器被称为&b&寄存器&/b&。&/p&&p&寄存器是用触发器实现的而触发器是用上面的4中所提到的各种门实现的。&/p&&p&举一个最简单的例子:&/p&&figure&&img src=&https://pic2.zhimg.com/50/v2-d63b42e80e4c786f4494_b.jpg& data-rawwidth=&343& data-rawheight=&110& data-caption=&& data-size=&normal& class=&content_image& width=&343&&&/figure&&p&其中,i为这个寄存器的输入,比如如果i是0(1),则表示希望该寄存器存储0(1);o为寄存器的输出,即该寄存器存储的值是多少;s的作用则是“告诉寄存器要工作了”,即当s为1时,寄存器会把i输入的值存储下来 ---- 也就是从o输出来。&/p&&p&另外,图中的1、2、3和4为&b&与非门&/b&。&/p&&p&与门电路是:两个输入都为1时输出才为1,否则输出均为0。即只要输入有0输出就是0。&br&与非门电路是:两个输入都为1时输出才为0,否则输出均为1。即只要输入有0输出就是1。&br&容易想到,与非门电路就是与门电路的输出的地方再接一个非门电路而实现的。&/p&&p&假设某个时刻,s是1,i是0,则根据上述与非门的规则,我们可以的到如下结果:&/p&&p&s = 1
i = 0&/p&&p&a = 1
b = 0&/p&&p&c = 1
o = 0&/p&&p&然后,此时我们让s也变成0,同理,可以得出o还是0;再然后,我们让i等于1,得出o还是0。这也就意味着,该寄存器成功保存了当s为1时i的值 ---- 也就是0。&/p&&p&同样地,当s和i均为1时,o为1;随后让s为0、i为1和s为0、i为0时,o均为1。也就是说此时寄存器是保存了1(当然还是在s为1时i的值)。&/p&&p&&br&&/p&&p&这就是寄存器的大致原理 ---- 只要不要断电保持1、2、3和4的正常工作,那么输入即使消失了也会被电路保存下来。&br&当然,实际的电路要比这个复杂,有兴趣的朋友可以自行阅读相关资料。&/p&&p&&br&&/p&&p&&br&&/p&&p&&br&&/p&&p&======================= BONUS3 ======================&br&关于5:逻辑电路实现四则运算。&br&我们先来考虑如何实现一位数(二进制)加法。&br&0 + 0 = 0(无进位:进位为0)&br&1 + 0 = 1(无进位:进位为0)&br&0 + 1 = 1(无进位:进位为0)&br&1 + 1 = 0(有进位:进位为1)&br&于是问题转化成了:&br&如何用那些门电路,设计一个逻辑电路,实现上述等号左侧的两个数值为输入,等号右侧的内容为输出(显然,这里需要两个输出,一个是加法结果另一个是进位)?&br&经过分析不难发现,加法的特点是两个输入一致时结果为0,两个输入不一致时结果为1;同时,只有当两个输入均为1时,进位才为1,其他情况进位均为0。&br&很显然,进位是一个与门电路。而结果呢?则是一种叫异或的逻辑关系:相同为0相异为1。&/p&&p&异或门电路有多种实现方式,这里只举一例:只用与非门(BONUS2中已讲过)实现异或门电路:&/p&&figure&&img src=&https://pic4.zhimg.com/50/v2-630dc8fdb39a7d1b9e62069_b.jpg& data-rawwidth=&300& data-rawheight=&100& data-caption=&& data-size=&normal& class=&content_image& width=&300&&&/figure&&p&到此,我们就可以实现上面的一位数的加法了:&/p&&figure&&img src=&https://pic1.zhimg.com/50/v2-d1aa8b1d82da0_b.jpg& data-rawwidth=&220& data-rawheight=&122& data-caption=&& data-size=&normal& class=&content_image& width=&220&&&/figure&&p&&br&&/p&&p&AB为输入,S为加法的结果,C为进位。S的左侧为异或门,C的左侧为与门。&br&这就是一个半加器。&br&至于半加器如何做成全加器,这里就不谈了,无非就是把多个半加器串联起来。有兴趣的朋友请自行了解。&/p&&p&实现了加法,则可以实现减法,因为减法等效于“加&b&负数&/b&”;也可以实现乘法,因为乘法可以转换成多次相加(例如,3 * 3等效于3 + 3 + 3);也可以实现除法,因为除法可以转换成多次相减(例如,7 / 2等效于7 - 2 - 2 - 2:一共减了3次且结果为1,因此7 / 2的结果为:商3余1)。&br&至此,四则运算全部实现。&/p&&p&&br&&/p&&p&最后只剩下了一个问题:如何实现负数。&br&以1和-1为例:&br&假设我们的加法器可以进行8位二进制的运算,我们用&b&最高位表示符号位:0为正数1为负数&/b&。&br&则1为:&a href=&tel:000001&/a&&br&-1为:&a href=&tel:000001&/a&&br&但这样1 + (-1)的结果并不是0,而是&a href=&tel:000010&/a&,也就是-2。&br&于是我们需要改变负数的表达方式:按位取反(除了符号位)。&br&&i&注:我们叫最原始的表达方式为原码,按位取反后的表达方式为反码。正数的反码和原码一样,负数的反码则是原码按位取反后所得。&/i&&br&因此,-1 = (&a href=&tel:000001&/a&)原 = (&a href=&tel:111110&/a&)反。&br&此时,1 + (-1) = (&a href=&tel:000001&/a&)反 + (&a href=&tel:111110&/a&)反 = (&a href=&tel:111111&/a&)反 = (&a href=&tel:000000&/a&)原 = -0&br&但这样还有一个问题,就是0和-0的表达方式不同:&br&0为:&a href=&tel:000000&/a&&br&而-0为:&a href=&tel:000000&/a&&br&对负数的反码做进一步处理:加1,形成补码。(正数的补码仍然是原码本身)&br&1 + (-1) = (&a href=&tel:000001&/a&)反 + (&a href=&tel:111110&/a&)反 = (&a href=&tel:000001&/a&)补 + (&a href=&tel:111111&/a&)补 = (&a href=&tel:000000&/a&)补 = (&a href=&tel:000000&/a&)原 = 0&br&&i&注:由于一共只能表示8位,所以最后溢出的进位被丢弃掉了。&/i&&/p&&p&&br&&/p&&p&说到这里,一定有朋友会说:&/p&&p&你别急!等一下!你说的这些原码反码补码都是理论,具体到电路中到底是如何实现的呢?&/p&&p&对于这样的问题我就不在这里做详细的解释了,因为它的原理和上面讲的门电路一样,无非就是通过不同的门电路的组合而形成一个复杂但有一定功能的“片子”罢了。(片子是行业黑话,高大上的说法是“芯片”)&/p&&p&以原码变反码为例,其实你可以自己设计一个片子,来实现:&/p&&p&输入是八个0或1,输出也是八个0或1。其中,当最左侧的输入为1时,则其他七位的数字全部取反输出;而如果最左侧的输入为0时,则八个数字全部原样输出。&/p&&p&在这里我仅以一位数字加上符号位(最左侧的位)来简单解释一下:&/p&&p&设符号位为A,输入为B,输出为C。容易得到如下的表(这个表叫真值表,是设计片子的重要手段)&/p&&div class=&highlight&&&pre&&code class=&language-text&&A
&/code&&/pre&&/div&&p&再重复一下:当符号位是0时,数字位原样输出;当符号位是1时,数字位取反输出。&/p&&p&观察真值表可得:当AB相等时C为0,AB不等时C为1。即,相同为0,相异为1 ---- 这就是一个异或门了。如何实现异或门上面已经说过了。可见,通过原码求出反码只需要用若干个异或门即可实现。&/p&&p&简单总结一下如何设计电路(这种和01打交道的电路叫做逻辑电路):&/p&&p&第一步:先分析需求,即你要输入什么、输出什么,根据输入和输出,做出真值表;&/p&&p&第二步:观察真值表,找到规律;&/p&&p&第三步:根据上面找到的规律,依据各种门电路的特点,完成逻辑电路的设计。&/p&&p&其中,第二步有的时候会非常复杂,难以一下子找到规律,如果不找规律就直接去设计逻辑电路,那么设计出来的逻辑电路会非常复杂。那么如何解决“找规律难”的问题呢?这就是大学里相关专业的数字电路课程的任务了......这里就不介绍了,如有兴趣,请自行百度:如何通过真值表写出逻辑表达式。我们设计逻辑电路其实就是根据逻辑表达式去做的,故只要确保逻辑表达式已经最简化,那么设计出来的逻辑电路就一定是最简单的。&/p&&p&&br&&/p&&p&&br&&/p&&p&以上,就实现了整数的四则运算,至于如何实现小数的运算,大同小异,只不过在计算机里是用科学计数法来表示的,在处理上会更加复杂。&/p&&p&&br&&/p&&p&&br&&/p&&p&&br&&/p&&p&&br&&/p&&p&====================== 什么是机器思维 =======================&/p&&p&问题一:如果要计算1加到100,应该怎么算呢?&/p&&p&人类:等差数列求和,有公式的:(1 + 100) * 100 / 2 = 5050&/p&&p&机器:愚蠢的人类啊,我们机器最大的长处就是“规律性地计算非常快”,所以我们不需要公式,只需要老老实实从1一直加到100就好了。&/p&&div class=&highlight&&&pre&&code class=&language-text&&a = 1
result = 0
语句标签(label):
如果(a & 100)
那么(执行label2)
执行标签:label
语句标签(label2):显示(result)
&/code&&/pre&&/div&&p&&br&&/p&&p&问题二:如何判断一个数字是否为偶数。&/p&&p&人类:用这个数字除以2,如果余数为0,则为偶数,否则为奇数。&/p&&p&机器:告诉你,人类,在我这里,/表示除法,%表示求余,我是不是很友好呀?&/p&&p&初级程序员:&/p&&div class=&highlight&&&pre&&code class=&language-text&&a = 用户输入
result = a % 2
如果(result = 0)
那么(显示(您输入的数字为偶数))
显示(您输入的数字为奇数)
&/code&&/pre&&/div&&p&机器:呵呵哒,愚蠢的人类,看来即使是程序员也不能真正懂我们的感受!我好伤心,你们知道要我做求余运算需要花多大的力气吗......&/p&&p&高级程序员:&/p&&div class=&highlight&&&pre&&code class=&language-text&&a = 用户输入
result = a & 1
// 按位与运算
如果(result = 0)
那么(显示(您输入的数字为偶数))
显示(您输入的数字为奇数)
&/code&&/pre&&/div&&p&&i&注:按位与运算(与运算:0 & 0 = 0
1 & 0 = 0 & 1 = 0
1 & 1 = 1)&/i&&/p&&p&&i&5 & 3 (十进制) = 101 & 011 (二进制) = 001 (二进制) = 1 (十进制)&/i&&/p&&p&&i&奇数的二进制的最后一位一定是1,偶数的二进制的最后一位一定是0&/i&&/p&&p&机器:眼泪哗哗的!这种位运算我最喜欢啦,因为对我来说最省力最简单了,这样的程序员给我来一打!&/p&&p&最后,送给各位一个小程序:&a href=&//link.zhihu.com/?target=https%3A//github.com/YvesZHI/FallingCode& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&YvesZHI/FallingCode&/a& (非程序员请绕行)&/p&&p&体验一下类似“机器表示求余运算很累人”的问题。&/p&
答案定位: 既不是儿童级别的读物,也不涉及高深晦涩和非常专业的词句。该答案的目的是让有初中文凭的人读懂。 前前言:所有读了这个答案但是有不懂的地方的朋友,恳请你们能告诉我哪里不明白,我会尝试用更通俗的话来阐述以帮助更多的朋友。谢谢! 前言: …
如果是题主所举的型号的话,那么恭喜你,黑屏,风扇转。hm6x系列虽然理论兼容3代i系列,但需要bios升级。目前为止我还没发现一个笔记本厂商提供过。&br&如果是同代或者往下换,windows会提示发现新硬件,过一小会提示驱动装完了要重启就好啦。但很多情况下核心显卡的驱动也要重新装。&br&如果脑洞再大一点,把两个电脑的硬盘互换了呢?&br&xp下似乎大多都通用,无非硬件没驱动而已。win7下除了i系列第一代换到除了hm55以外的板子一换一蓝屏以外,基本都可以正常开机。。。到了win8以上,i系列第一代也没问题了。windows可怕的兼容性啊。。。&br&如果脑洞更大一点,换了一个热功耗比自身大的呢?&br&看到题主还提到了散热,这个还真是得分本子。如果是如题主所举得例子来讲,功耗是不会变的,会略微热一点但绝对在控制范围内。如果35w的系统强行上了45w乃至更高功耗的cpu,就我自己认知而言,一般情况下是没问题的。如果你十分丧心病狂,把超极本的cpu bga下来,换一个标准电压的上去,也不是不能用,降频、锁一个核心呗。我做过最丧心病狂的事情是把用7瓦u1400 cpu的小本生生放上去一颗35w的t2300,降频锁核心一样用。放开锁一分钟内直接高温断电妥妥的。&br&如果你干的不是这种直接把原来的热功耗扩大五倍的事情,那么散热一般是没有问题的。&br&但是,如果本子本身的供电电路功率不够,很有可能导致你换上去的这颗cpu不能跑出最佳状态,我并不很专注于游戏本,听说过这个事情而已。另外有些笔记本的bios会对cpu的频率作出限制。比如我戴尔m3800里面的4702hq就只能睿频到2.9,插小功率电源的时候直接锁死在800mhz,那个时候整机功耗40w以内。。。简直屌
如果是题主所举的型号的话,那么恭喜你,黑屏,风扇转。hm6x系列虽然理论兼容3代i系列,但需要bios升级。目前为止我还没发现一个笔记本厂商提供过。 如果是同代或者往下换,windows会提示发现新硬件,过一小会提示驱动装完了要重启就好啦。但很多情况下核心…
有Mac多好啊,程序员行走江湖的神器,Mac慢慢用起来之后你很难回到Windows了。&br&&br&学习Java要熟悉框架的话,Spring是必然选择,学习Spring的话结合Spring Boot来学习事半功倍,涉及到Spring MVC以及Spring Data JPA等。学习Spring依赖注入等基本原理,Web端的MVC框架和数据访问的ORM框架,两三个月应该足够了。&br&&br&推荐你一个非常非常棒的Spring的教程,基础知识和实战项目结合得非常好。&br&&br&今天更新一下(09-26),把Spring MVC的部分专门提出来,重新优化了一下内容,大家学习Spring MVC可以看下面的内容:&br&&br&第1课 &a href=&//link.zhihu.com/?target=https%3A//course.tianmaying.com/spring-mvc/lesson/start& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&创建Spring Boot项目&/a&&br&第2课 &a href=&//link.zhihu.com/?target=https%3A//course.tianmaying.com/spring-mvc/lesson/router& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&URL路由:@Controller和@RequestMapping&/a&&br&第3课 &a href=&//link.zhihu.com/?target=https%3A//course.tianmaying.com/spring-mvc/lesson/path-variable& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&@PathVariable&/a&&br&第4课 &a href=&//link.zhihu.com/?target=https%3A//course.tianmaying.com/spring-mvc/lesson/request-param& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&@RequestParam&/a&&br&第5课 &a href=&//link.zhihu.com/?target=https%3A//course.tianmaying.com/spring-mvc/lesson/template& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&模板渲染&/a&&br&第6课 &a href=&//link.zhihu.com/?target=https%3A//course.tianmaying.com/spring-mvc/lesson/paging& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&分页处理&/a&&br&第7课 &a href=&//link.zhihu.com/?target=https%3A//course.tianmaying.com/spring-mvc/lesson/form& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&表单提交&/a&&br&第8课 &a href=&//link.zhihu.com/?target=https%3A//course.tianmaying.com/spring-mvc/lesson/validation& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&表单验证&/a&&br&第9课 &a href=&//link.zhihu.com/?target=https%3A//course.tianmaying.com/spring-mvc/lesson/flash& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Flash Attribute&/a&&br&第10课 &a href=&//link.zhihu.com/?target=https%3A//course.tianmaying.com/spring-mvc/lesson/interceptor& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&拦截器Interceptor&/a&&br&第11课 &a href=&//link.zhihu.com/?target=https%3A//course.tianmaying.com/spring-mvc/lesson/http-method& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&处理PUT和DELETE请求&/a&&br&第12课 &a href=&//link.zhihu.com/?target=https%3A//course.tianmaying.com/spring-mvc/lesson/file& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&文件上传&/a&&br&第13课 &a href=&//link.zhihu.com/?target=https%3A//course.tianmaying.com/spring-mvc/lesson/exception& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&异常处理&/a&&br&第14课 &a href=&//link.zhihu.com/?target=https%3A//course.tianmaying.com/spring-mvc/lesson/rest& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&@ResponseBody与@RequestBody&/a&&br&&br&原来教程地址:&a href=&//link.zhihu.com/?target=http%3A//course.tianmaying.com/web-development& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&web-development&/a&&br&&br&&p&这个课程基于Java语言和Spring框架,通过实例的项目案例,你可以学到开发一个成熟Web应用所需的所有关键知识和经验:&/p&&ul&&li&开发环境的建立与项目管理:Eclipse、Maven&/li&&br&&li&Spring基础:IoC、AOP、SpringBoot&/li&&br&&li&Spring MVC:URL路由、模板、表单、Session、拦截器等&/li&&br&&li&数据访问:关系型数据库、JDBC、JPA、事务&/li&&br&&li&成熟应用的关键功能实现:邮件发送、异步任务、缓存、日志等&/li&&/ul&&br&下面是课程目录:&br&&br&第1课 &a href=&//link.zhihu.com/?target=http%3A//course.tianmaying.com/web-development/lesson/environment& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&开发环境建立&/a&&br&第2课 &a href=&//link.zhihu.com/?target=http%3A//course.tianmaying.com/web-development/lesson/maven& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&使用Maven进行项目管理&/a&&br&第3课 &a href=&//link.zhihu.com/?target=http%3A//course.tianmaying.com/web-development/lesson/eclipse& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Eclipse的使用&/a&&br&第4课 &a href=&//link.zhihu.com/?target=http%3A//course.tianmaying.com/web-development/lesson/spring-boot& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&第一个Spring Boot项目&/a&&br&第5课 &a href=&//link.zhihu.com/?target=http%3A//course.tianmaying.com/web-development/lesson/spring-ioc& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Spring的IoC原理&/a&&br&第6课 &a href=&//link.zhihu.com/?target=http%3A//course.tianmaying.com/web-development/lesson/spring-aop& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Spring的AOP原理&/a&&br&第7课 &a href=&//link.zhihu.com/?target=http%3A//course.tianmaying.com/web-development/lesson/url-route& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&创建URL路由&/a&&br&第8课 &a href=&//link.zhihu.com/?target=http%3A//course.tianmaying.com/web-development/lesson/resources& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&静态资源&/a&&br&第9课 &a href=&//link.zhihu.com/?target=http%3A//course.tianmaying.com/web-development/lesson/template-rendering& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&模板渲染&/a&&br&第10课 &a href=&//link.zhihu.com/?target=http%3A//course.tianmaying.com/web-development/lesson/form& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&提交表单&/a&&br&第11课 &a href=&//link.zhihu.com/?target=http%3A//course.tianmaying.com/web-development/lesson/form-validation& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&表单数据验证&/a&&br&第12课 &a href=&//link.zhihu.com/?target=http%3A//course.tianmaying.com/web-development/lesson/redirecting& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&页面重定向&/a&&br&第13课 &a href=&//link.zhihu.com/?target=http%3A//course.tianmaying.com/web-development/lesson/session& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Session&/a&&br&第14课 &a href=&//link.zhihu.com/?target=http%3A//course.tianmaying.com/web-development/lesson/interceptor& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Interceptor&/a&&br&第15课 &a href=&//link.zhihu.com/?target=http%3A//course.tianmaying.com/web-development/lesson/handle-exception& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&异常处理&/a&&br&第16课 &a href=&//link.zhihu.com/?target=http%3A//course.tianmaying.com/web-development/lesson/file-uploading& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&文件上传&/a&&br&第17课 &a href=&//link.zhihu.com/?target=http%3A//course.tianmaying.com/web-development/lesson/rational-database& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&关系型数据库&/a&&br&第18课 &a href=&//link.zhihu.com/?target=http%3A//course.tianmaying.com/web-development/lesson/spring-jdbc& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Spring JDBC&/a&&br&第19课 &a href=&//link.zhihu.com/?target=http%3A//course.tianmaying.com/web-development/lesson/spring-data-jpa& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Spring Data JPA&/a&&br&第20课 &a href=&//link.zhihu.com/?target=http%3A//course.tianmaying.com/web-development/lesson/transaction& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Spring事务处理&/a&&br&第21课 &a href=&//link.zhihu.com/?target=http%3A//course.tianmaying.com/web-development/lesson/spring-mail& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&发送邮件&/a&&br&第22课 &a href=&//link.zhihu.com/?target=http%3A//course.tianmaying.com/web-development/lesson/spring-task& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Spring任务&/a&&br&第23课 &a href=&//link.zhihu.com/?target=http%3A//course.tianmaying.com/web-development/lesson/cache& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&缓存&/a&&br&第24课 &a href=&//link.zhihu.com/?target=http%3A//course.tianmaying.com/web-development/lesson/logging& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&日志&/a&&br&第25课 &a href=&//link.zhihu.com/?target=http%3A//course.tianmaying.com/web-development/lesson/ajax& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&AJAX&/a&&br&第26课 &a href=&//link.zhihu.com/?target=http%3A//course.tianmaying.com/web-development/lesson/markdown& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&支持Markdown&

我要回帖

更多关于 计算机专业都学什么 的文章

 

随机推荐