第1章 0的故事
计数法分为按位计数法和罗马计数法
按位计数法常用的有2进制、8进制、10进制、16进制等几种。
理论上多少进制在数学上都可以存在,玛雅人用20进制,巴比伦人用10进制和60进制的混合计数法。玛雅人20进制可能是和手脚趾加起来的数量有关。巴比伦人采用60进制也可能是因为记录数字的黏土版比较难记录文字记号,为了在大数的书写上少占位便采用了60进制。
从这一点来看,环境对文明和文化的形成真的是有决定性的影响。假如巴比伦人掌握了造纸术或者在竹子上书写文字的话,60进制这种违反人类天性的计数方法一定不会出现。话说,汉莫拉比法典就是写在黑色的玄武岩上的。能够记录的文字也就屈指可数吧。
作者提到了其实人也是可以采用2进制计数法的,可是同样大小的数字用2进制书写起来位数太多,一来书写不方便,二来计算时易发生马虎出现错误。而10进制的数天生就是顺应人类人性的,即使是幼儿也可以通过数手指头的方式来计数。
相反对于计算机的物理构造来讲,0代表开关断开,1代表开关连接,这种二极管的物理限制正好决定了计算机较为适用2进制。不过如果你想做出一个10进制的计算机也不是没有可能的。
这一章比较有趣的是罗马计数法,我以前也没有接触过超过20的罗马数字,也不知道罗马数字各个数位上的数字相加之和为数字本身所代表的量。例如:
MCMXCVIII=M+CM+XC+V+III=1000+(1000-100)+(100-10)+5+3=1998。
其中各个字母所代表的阿拉伯数字如下所示:
I(1),V(5),X(10),L(50),C(100),D(500),M(1000)。
反观阿拉伯数字
1998=1×103+9×102+9×101+8×100
每一个不同的数位上的数字所代表的数量并不一样。
k位上的数字n所代表的数量是n×10^k-1。
由此引发作者在两个程序领域上的思考:
- 0的意义更多的是:空、占位符。
例如2503里的0,如果0去除,则会变成253,0的意义在于占位和表明空值。
2的0次方意味着2的1次方的1/2。作者还举到一个例子,避孕药一月需要有7天不能吃,这7天可以引入0的空值(代表无任何疗效的安慰药)进行占位。这样一来我们就不用花费心思计算吃药的时间上了。
- 从罗马计数法中同样的12可以表示为IIIIIIIIIIII或XII,前者相对来讲无法一眼准确计算出数值。也就是说数值越大越难处理。所以把5个I用V表示,10个I用X表示,100个I用C表示。这种方法的思想精髓是将大问题分解为小的单元(模块),一个个来分别解决。
第2章 逻辑--真与假的二元世界
关键词:真值表、文氏图、逻辑表达式、卡诺图、三值逻辑、完整性、排他性
-能够判断对错的陈述句叫做命题(proposition)
1.注意边界值(很多程序爱犯的错误)
2.兼顾完整性和排他性
没有遗漏--完整性
没有重复--排他性
逻辑非--不是A
逻辑与--A并且B
逻辑或--A或者B
逻辑异或--A或者B(但都不满足)
逻辑相等
逆命题
A=>B是B=>的逆命题,反之亦然。
逆否命题
┐B=>┐A是A=>B的逆否命题
德摩根定律
卡诺图(二灯游戏、三灯游戏引出)
命题A 绿灯亮
命题B 黄灯亮
命题C 红灯亮
未定义逻辑(undefined)
涉及到三个值
true 真 ; false 假 ; undefined 未定义 ;
-带条件的逻辑与(&&)
-带条件的逻辑或(||)
-三值逻辑的否定(!)
三值逻辑的德摩根定律
第3章 余数——周期性和分组
本章探讨的是通过余数来解决存在规律、周期性的问题。通过规律和周期性的重复,将大问题简化成容易解决的小问题。
首先作者通过解决星期几问题,引入了余数的思考概念。
100天后是星期几是一个简单的通过余数解决的问题。
10^100天后是星期几是一个放大概念的余数问题(实际上是在利用余数思维之前同时用了规律性解决问题的思维),通过研究10的n次方与7除的余数,找到余数的规律。解决问题的本质思维是余数的平方(或者说是规律的平方,意指规律嵌套在规律中)。
上面的问题在大问题通过余数规律简化为小问题这个方法上表现的还不明显,于是引入了第三个问题:1234567^7654321的个位数是多少。
这个问题可以简化为7^7654321的个位数是多少,同样通过规律嵌套思维可以轻易的解决问题。
以上三个问题是小学奥赛便涉及到的问题,然而其思想在解决真实面对的复杂问题或具象的实际问题时却很好用。
将一个数字除以2,他的余数应该为0或者1二者之一。我们也可以叫奇偶问题。
书中有几个案例:
1.魔术师与徒弟通过奇偶问题判断观众是否翻转棋子(这个实际看起来有点弱智)
由此引出了计算机专业里的【奇偶校验】
2.在8个村子里找恋人(恋人每隔一月便去相邻村子,一年前在G村,问现在在A村的概率),村子之间的图如下
同样是通过规律嵌套思想解决问题,但 规律一定是建立在前期试验的基础之上!
3.铺设草席问题(如下图所示,在不分割草席的情况下,是否可以铺满房间)
这个问题的解决方法真是好犀利。通过把草席进行黑白各一半的染色与房间对照。计算房间内的黑白块数是否相等来判断。解决问题的思想与前几种不太一样。
4.哥尼斯堡七桥问题
相信每个学过数学的人都接触过七桥问题。如下图所示,可否一次性走遍所有桥,但每个桥只走一次?
解决这个问题方法是,1.简化问题,简化地图为如下:
2.研究通过每一块土地(所谓顶点ABCD)所需要经过的桥梁数量(引入入口和出口的概念,经过过程中的每一个点,也就是土地,均涉及到来时的桥(入口),和走时的桥(出口))
1)假设起点终点都在一地,路线上起点经过的桥梁数为1,其他点均为2,终点为1,故所有点(土地)都是偶点,起点和终点是一个点也为偶点。
2)假设起点终点不在一地,起点终点均为奇点,其他点都为偶点。
这样分析过来就很好解决七桥问题,确定每个点所连接的桥的点数,与上述结论做对比。
A点为3,B点为,C点为3,D点为3.
由此可以得出七桥问题不可能实现。这个问题的解决也是通过奇偶性来解决的。
第4章 数学归纳法——如何征服无穷数列
作者举了高斯求和的故事来讲如何用数学归纳法来解决无穷数列的求和问题。
两个小例子便是从0开始到N的和,以及1开始的奇数和。
数学归纳法是证明[有关整数的断言对于0以上的所有整数(0,1,2...)是否成立]所用的方法。
证明方法归结为两歩:
1(被称为基底).证明“P(0)”成立
2(被称为归纳).证明不论k为0以上的哪个整数,“若P(k)成立,则P(k+1)”也成立。
根据上述方法,假若某个假设成立,那么P(0)成立,因为P(0)成立,所以P(0+1)即P(1)也成立。反复如此,对于无穷数列遵守这个规律的证明,就像多米诺骨牌,推到第一个,后面的都会按照第一个的规则倒下去。
然而要避免整个证明出错,就要重视第二个步骤,也就是归纳。归纳在证明时一定要考虑是否在所有定义条件下均成立,尤其要注意的是在P(0)的条件下是否实现。
课后对话很有意思:
-首先假设一条腿可以往前迈一步
-然后假设另一条腿无论什么情况都能迈出去
-那样的话,就能够行进到无限的远方。这就是数学归纳法。
第5章 排列组合——解决计数问题的方法
计数是人类每天生活都要运用的方法。
计数的关键就在于注意“遗漏”和“重复”
例如:
一条10米的路每隔一米种一棵树,需要多少棵,如果回答10,就是遗漏了最头或最尾的一棵树。这就是所谓植树问题
再如:
运动员从0开始编号,第100名运动员是第几号。如果忽略了重复问题,可能会马虎的回答100号。
综上,在计数时要发现事物的规则。
要认清计数对象的本质
要认清计数对象的本质
要认清计数对象的本质
重要的事情说三遍。
将计数对象进行归纳总结,使其作为普通规则来掌握。这样一般不容易出错。
接下来,作者在加法法则里写到:
不同集合A、B相加,元素总数为A U B的元素数,前提是AB集合没有重复的元素。
有重复元素的情况下,作者引出“容斥原理”,有些类似于文氏图。
在使用容斥原理时,必须弄清楚重复元素的个数。
乘法法则的概念比较有意思。
当A*B这个式子出现时,可以理解为:A为集合的元素数,B为相同集合的集合数。这样结果变为了求相同的N个集合的元素数。
接下来,本章提到了置换、排列、组合3个概念。以下是几个小例子。
置换:3张牌在有顺序的排列下的排法数。
排法可以写成阶乘(factorial)n!。
排列:5张牌抽3张进行有顺序的排列的排法数。
文中用树状分叉图来形象展示。排列(permutation)的缩写用P来展示。
组合:5张牌抽3张的组合数,不涉及顺序。
组合可以看成排列的数除以置换的数(相同组合下不同的排法,如AB BA都是一个组合),即先考虑顺序进行计数,然后除以重复度,如下图:
最后提到的重复组合里的思考问题比较有趣。
ABC3种药,共取100粒,并且保证ABC每种都至少有1粒。在不考虑药品调剂的顺序时,问药品调剂的组合有多少种?
解答的思想是:
1.n粒药的容器一条直线摆开,中间有n-1个空隙。
2.有两个隔板可以隔开3种药,最左边放A,中间放B,最右边放C。
3.问题变成在n-1个空隙中,插入2块隔板有多少种方法。
这是一种典型的将复杂问题简单化,并规律化的解答方法。
最后还是要强调下:
要认清计数对象的本质
第6章 递归——自己定义自己
递归与归纳的区别
递归(recursive)是从一般性前提推出个别性结论。
归纳(inductive)是从个别性前提推出一般性结论。
本质上都是将复杂问题简化,但方向不同。
个人理解是
递归属于老老实实工作推倒,归纳属于投机取巧,所以叫个别性前提。
递归是发现第n项和前一两项之间的关系,实证确定后,往回不断递推的一种个别性结论。
即这个结论不是在n为任何自然数时都成立的。需要注意n为0和1的两项。
通过递归解决问题的线路是:找到递归结构——建立递推公式——找到解析式(只带n的式子),如果不能以解析式的方式描述递归结构,也可以用递推公式的方法描述。如下图所示的汉诺塔的递推公式:(它也可以描述成解析式的方式)
归纳所谓的个别性前提是指
他通过假设n成立,来求解是否n+1成立,来实现逻辑推倒得出结论,这个结论是一般性的,因为n可以为任意数。
斐波那契数列就是运用了递归的思想。通过研究和思考复杂问题,抓住事务本质,得到f(n)=f(n-1)+f(n-2)
所以当我们想要用递归的方法解决问题时,注意思考第n元素与前后元素的关系。由一个点推开,成一条贯穿始终的线。
利用帕斯卡三角形来研究Cnk=Cn-1(k-1) + Cn-1k的思考方式另辟蹊径。将两个加数假设成组合问题里含一个元素和不含那个元素的两个情况。从而证明了式子。利用的便是组合的数学分析法。(这句话组合的意思不是数学意义上的)。
所以以上将复杂问题简化的方法是递归解法之一,是为了在复杂问题中找到隐含的递归结构。其思路是:
1.从整体问题中隐去部分问题(隐去部分相当于上面的特定牌)。
2.判断剩余部分是否和整体问题是同类问题。
也就是:
1.从n层的整体问题中隐去部分问题。
2.判断剩余部分是否是n-1层的问题。
第7章 指数爆炸——如何解决复杂问题
通过思考一张1mm的纸,折多少次能够有地月距离那么厚,作者引出指数的概念。
这一章的内容比较简单,对于指数爆炸大家应该都不陌生。而对数估计也很熟悉。之前接触到的汉诺塔问题的解析式和斐波那契数列都属于指数的范畴。
然而在解决测试所有设定选项的程序时,检查次数也是一个指数问题。所以我们应该如何轻松的解决这类问题呢?
利用二分法查找
在15个罪犯里找到唯一的那个罪犯的方法只能是一个个问,那么当我们问一个人时,他可以有3种回答:
1.我是罪犯
2.罪犯在我左边
3.罪犯在我右边
利用二分法,先询问最中间的人,如果在左边,就继续在左边的范围内重复此项方法,直到找到罪犯。这便被称为2分法。他和汉诺塔的解析式如出一辙,可以利用指数原理经过很少的步骤便可找到目标。
二分法本身也是递归结构,经过n次询问,可以在2^n-1人中确定目标。每判断一次就可以查找近一半的对象。
二分法需要注意的是,所有元素一定要按顺序排列,这点至关重要。
指数思想也被用于加密的实现中。因为每多加密一位,暴力破解就需要指数次的运算能力的提升。原则上有限时间里根本不可能破解。指数以其数字的巨大增长能力在加密领域有基本性的作用。
对于指数问题的解决方法,主要有4种,但均不太容易应付规模大的数字。
1.极力求解
类似于暴力破解
2.变相求解
把问题转化成简单的问题,应用起来很难。
3.近似求解
有助于实际应用,结果不准确
4.概率求解
利用随机数,可能比较快的得出结果,但也可能运气不好永远也找不到结果。
作为指数函数的逆函数,文章涉及了对数。同时也简单介绍了古代科学家用过的计算尺。
第8章 不可解问题——不可解的数、无法编写的程序
无穷可以分为可数无穷和不可数无穷。
所谓可数无穷是指可以按照一定的规律或者表达方式来表达。
即集合中所有元素都与正整数一一对应。如果每一个元素都可以与1.2.3....等数字对应,也就是说可以按规律表达出来就是可数无穷。
例如:
-有限集合是可数的
-0以上的所有偶数的集合是可数的
-0以上的所有奇数的集合是可数的
-所有整数的集合是可数的
-所有有理数的集合是可数的
-程序的集合是可数的
因为编写程序的字符种类有限,假设为N个,则由k个字符组成的字符串有Nk个,而真正成为程序的字符串远比Nk小,无论如何都是可数的。
所以有不可数的集合吗?
此时运用到了对角论证法和反证法(也叫归谬法)
假设我们要证明所有整数数列的集合是不可数的,那么反证就是假设所有整数数列的集合是可数的,此处是运用的反证法。
现在我们按下图的方式来列出所有整数数列,编号为k的整数列在表的k行。
如果按照图中第k行的第k个元素ak单独组出一组数列{a1,a2,a3......}的话,他也是应该包含在所有整数数列里的,然而并没有,他是游离在所有整数数列之外的。此处得出矛盾,说明命题错误,命题所有整数数列的集合是不可数的为真。此方法被称为对角论证法
除此之外
-所有实数的集合是不可数的
-所有函数的集合也是不可数的
随后书中讨论到了不可解的问题
对于不可解的问题的定义是
原则上不能用程序来解决的问题。
事实上,不能写成程序的函数是存在的。
有些函数不能用文字表达,而且要写成程序的函数必须严谨定义确切和文字表达两个概念。
停机问题
不可解问题的一例。定义是
某程序在给定数据下,是否会在有限时间内结束运行。
程序有两种可能,一种是会在有限时间内结束运行
另一种是改程序永不结束运行。
有限时间并不指时间长短,而是指无论耗时多长,只要能有终止的一刻就好。
事实上,程序本身并不能判断某一程序是否可以在有限时间内结束运行
所以停机问题也是不可解问题之一。
第9章 什么是程序员的数学——总结篇
这一章是对之前8章的回顾和总结。
前几章作者分别对0的意义、逻辑、余数、数学归纳、排列组合、递归、指数爆炸、不可解问题进行了简单的介绍和探讨。其实所有的章节最后都是在引领读者产生如何解决问题的思考。
1.认清模式,进行抽象化
解决问题中,我们常常用简单的数字进行规则的探寻,对问题进行抽象化的思考。这是解决问题中惯用的套路。
2.由不擅长催生出的智慧
人类的物理生理特性决定了其在很多事情上的不擅长,例如对处理大规模数字、复杂判断等,但通过方法,可以使复杂不擅长的事情变得简单。
3.幻想法则
其实就是把问题换一种思考方式而已。不按套路去出牌。
本书比较适合作为第一本接触算法的书籍。目前开始在上Khan的Algorithms,9月份跟上coursera的Algorithms Part I的开课。
前方的路注定不好走,但是要慢慢尝试和坚持。