复旦计算机系最值得上的课《计算机原理》,没有之一!

最近在上金博的《计算机原理》。为什么说是最值得上的课,原因有二。

一者,教材是CMU的人写的久负盛名的《Computer Systems:A Programmer’s Perspective》(http://book.douban.com/subject/1230413/),从一个程序员的角度看待计算机的硬件,没有太clip_image002多的硬件理论知识,而是以如何结合硬件和编译器的角度去写出更高效的程序,debug出那些诡异的错误,如何真正的理解一个程序从启动到运行结束到底在硬件上做了什么,这本书提供了很好的支持。所以这课不像计算机体系结构那般,整天教CPU、流水线、SRAM之类的,我们将来实际不太会接触的理论,此书更注重实践。

第二个原因,就是老师上得确实很不错。为什么说老师上的不错?启发式教学。很久很久都没有这么喜欢一门课的感觉,每堂课我都全神贯注努力地思考,生怕漏掉某个细节某个思维的环节,我再一次在课堂上体会到了思维的乐趣。本科时候,极少是有那么些课、那么些老师是真正注重学生是如何思考的。把知识教给学生不就行了吗?学生也更注重绩点,只要是能把要点教给自己的,能让自己得个高GPA的都是好老师。说实话,GPA确实重要,但仅仅为GPA就太悲剧了,至少有那么些课那么些自己喜欢的课,应该从中得到乐趣才不枉此行。一个善于教的老师,有时确实能改变激发一个学生对于某个领域的兴趣;而一个平庸的老师,或许就能让一个出入茅庐的学生对某个领域恐惧、深恶痛绝。

举个简单的例子,金博(金城)在教32位浮点数在计算机硬件中的表示时,并没有直接把浮点数是如何表示的写在黑板上,而是问底下的学生如何去设计?如何去合理地用32个bit去分配这个数的表示?应该用哪些条件去判断这样分配是合理的?金博用了整整3节课的时间去讨论,学生们提出方案,然后大家一起讨论优劣,几乎每个学生都在思考,数的表示范围?指数的应占位数?用2为底或是10为底?这可以说也是设定IEEE委员会的人在设定标准时所考虑到。提出的方案汇总如下:

最简单的想法就是把位中的一部分用作整数,另一部分作为小数,于是有同学提出这样的方案:

clip_image003

如何表示负数呢?整数用补码表示就行了,而小数则可以用原码。一半用作整数,一半作为小数。自然,我们可能会想到可能这样表示的数表示范围有点小,而且精度似乎也有点不够。这样的数大小范围大约只有一般的32位整数的一半,实在有点说不过去。

那么想个改进的方法吧。又有同学想出如下方案:

N:小数点移动2^N位,补码表示,如果为负就向左移动,反之向右。

D:补码表示。

clip_image004

所表示的数就是:D然后小数点移动2^N位(小数点在D的末尾),这样看上去好多了,比上一种方法的表示数的范围大了很多,而且进度更高。

那么还有改进的方案吗?于是又有同学分别提出了以2为底的指数表示,相继又有同学质疑为什么一定要用2为底,不能用10为底吗?方案如下:

S:符号位;E:指数位,补码表示;D:数字位,

clip_image005

如图,以10为底和以2为底的方案哪个更好些呢?E的位数又该如何确定呢?在D的表示中为什么要把这部分表示为小数部分?那假定是小数整数部分该设为是1还是0呢?

先以2为底的情况讨论,数的表示为:(-1) * S * (1/0?).D * 2^E

如果整数部分是1会怎么样?那么很自然会发现一个问题,0怎么表示,虽然这个数可能足够小,但它依然不是0。那么整数部分是0呢?现在0可以表示了,但会发现D=0时,E无论怎么表示数值都是0,也就是有2^E个0,这样无疑会造成很大的浪费。那么该如何解决呢,现在似乎没法很好的解决方案,那先把整数部分设为0吧,至少0可以表示了。

另一个问题是E的位数如何确定?E的位数太大,那么小数部分精度会减小;E太小,那么数值的表示范围[min, max]会减小。这时,大家只能在这两者之间折中一下,于是拍脑袋选了个8位作为E的位的大小,至于为什么?则有待探讨。最后以2为底的数表示范围就可以确定了。

之后的工作是极其精细地依次分析各种表示方法的表示进度,数的大小,以及到底以10为底还是以2为底?

(由于更多的分析要费太大篇幅,在此省略1000字)

金博几乎说的很少,以同学为设计师的我们则是一步一步地在金博带领下启发式分析各种表示的优劣。这是个很费神的工作,但却能够这么分析一把,确实能很真切体会一下当时为何标准是这样制定而不是那样。即使离最后的标准还有一定距离,但思考本身就比最后的结果重要得多。

通过以上的思考,我们制定的标准和IEEE已经十分接近了,IEEE在指数的处理上用了一个trick,设定一个bias=127指数是原码表示-bias,另外,在D的表示方法上也有一些特例情况,这样能方便地表示出正无穷、负无穷和0的特殊情况。但我们所做的工作大部分已经很接近标准了,可见学生同样能像那些专家一样思考,只是你想不想的问题。思维本身就是一种乐趣,放弃了自己的,全然去接受别人的,不觉可惜吗?上课不在于能学会多少知识,更重要的是能学会思维的方法,触类旁通,以后学什么都很简单。知识就像是硬盘里的数据,而学习知识的思维方法就像是算法,在这个信息时代还怕没有海量的知识吗?到处都是。问题是如何处理这些知识,如何鉴别真伪,如何运用自如才是真正的关键。

这样的启发式提问出现了很多次。例如,为什么汇编的指令操作数最多为2而不设定3,这样不是更方便?为什么不把硬盘和内存做得一样快呢,这样不就是不用内存了吗?为什么要用补码而不是用反码,取反加1不觉得很不自然吗?所有的问题,老师几乎都不会正面回答而是引导学生去思考,这是最为经典的地方。设身处地的想想自己会如何做,而不是死记别人的思考结果,就算想错了也是莫大的收获。

记得pongba最喜欢说一句话:“问题的本质是什么?”,金博似乎就一直在询问着学生这么个问题,实在太绝了。这里另一句话:五流老师混日子,四流老师教知识,三流老师教技能、二流老师教思维,一流老师教信念。

最后还是要说,这课无疑是计算机科学中非常非常基础的课,怎么说它的重要都不为过,如果真能学好的话,必定是能够和没学过的同志拉开一个数量级的距离。另外,老师又教得有声有色。实在是不可多得的享受,就像和美女聊天一样,实在是无聊不起来。

原文地址:https://www.cnblogs.com/chkkch/p/2011914.html