程序员入伙书——编程语言

下载Python一章里,我说过请大家忽略“编程语言”和“Python”这些词的意思,因为那时这些词并不重要。

现在大家已经看到了一些使用Python的实例,我想是时候让大家了解关于编程语言的一些知识了。如果你懒得听我长篇大论,可以直接跳到文章结尾看总结。如果觉得我的扯淡还有点意思,请继续往下读。

我们说过,计算机不会自主思考,它所有的动作都是人们事先告诉它的。告诉计算机”遇到什么情况时该干什么“,就是编写程序,简称编程。既然要给机器发指令,它就得明白这些指令。

计算机本身能明白的、以及能操作的东西,只是一系列高低电平的组合,就像我们人类的身体只有一系列的化学反应和生物电一样。一个刚生下来的人只会吃、哭、拉、睡,却不知道怎么喊妈。你让他喊他也不会喊,因为他听不懂。在计算机世界里,我们把这种基础的电平称为“机器语言”,机器语言是在制造计算机芯片时固化在那块半导体里面的。

使用机器语言能编程么?能!你拍打婴儿的脚底板,痛觉末梢产生一些生物电,传送到大脑,他就开始嚎哭。“拍脚”是指令,“嚎哭”就是动作。较真的同学会说我这个比喻不恰当,因为“拍打脚底板”是婴儿大脑里运行的那个小程序的输入,“哭声”是程序的输出,无论“拍脚”还是“哭声”都不是程序本身。我首先感谢这位同学,提出这个质疑,说明你认真地看了前头的章节。其次,我解释说:判断这些行为究竟是输入输出还是程序本身,得看你怎样定义这个系统的范围。假如我在计算机芯片的一些管脚设置成事先想好的高、低电平,之后,在芯片的另外一些管脚上观测到了一次乘法的计算结果(同样是高、低电平来表示),我们既可以把设置的那些电平称为程序,也可以把它们称为输入数据。

跑题了,拽回来。刚才说到,计算机只能听懂高低电平组合成的机器语言。为了显得专业些,我们把高电平称为1,把低电平称为0。计算机里只有两个数字:0和1。我们眼前的计算机有许多花里胡哨的行为,能显示种种色彩,发出种种声音,那都是它组合各种0和1的结果。举个例子,一个橙色的像点至少包含24个电平,顺序是111111111000000000000000。一个灰色的像点则可能是100111011001110110011101。字母“A”在计算机里是01000001,而“#”在计算机里是00100011。
猛击阅读全文

程序员入伙书——初涉算法

在以后的讲解里,会陆陆续续地涉及到许多算法。所以这里先给大家心里垫个底儿。如果你没有看明白这一节,不用很担心。

在“程序在干什么?”一节的最后,我举了一个例子,来说明程序具有计算、流程控制、输入输出三个功能块。这个例子是“求”一个数字的平方根,但它不是在“算”,而是在“猜”。

如果我给它的数是3,它就先猜:1.5!然后自己验算一把:1.5 x 1.5 = 2.25,太小。于是它就再猜:2.25!(就是位于1.5和3正中间那个数)验算一下:2.25 写2.25 = 5.0625,太大。再猜:1.875!——1.5太小,2.25太大,那一定在它们之间了。1.875是1.5和2.25的平均值。1.875 x 1.875 = 3.515625,又大了些,不过大家可以注意到,数字开始接近3了。于是它再取1.875和1.5的平均值……如此反反复复地接着猜下去,可以预知,猜测的结果必然会越来越逼近3的平方根。

我们都知道,第一、计算机无法精确表达实数。第二、即使从完美的数学上说,3的平方根是一个无理数,也不可能通过有限次的有理数四则运算实现。所以我就对程序说,你也不用太自责,只要误差小于亿分之一,你就可以从循环里退出来了。这样就不会出现这种情况:由于结果的平方总是不能精确等于3,程序过于内疚而陷入无限循环的困境。

现在咱们往那个程序里加两条调试语句:

print('Please input a number: ', end = '')
n = abs(float(input()))
high = max(1, n)
low = 0
while True:
    result = (high + low) / 2
    print('What about %.10g?' % result)
    print("%.10g x %.10g = %.10g" % (result, result, result * result))
    if abs(result * result - n) < n * 1E-8:
        break
    if result * result > n:
        high = result
    else:
        low = result
print('Square root of %g is %g' % (n, result))

再来跑一下,看看每次循环的中间结果。
猛击阅读全文

程序员入伙书——程序在干什么?

程序员是写程序的,程序是干什么的?

我的独门总结:形形色色的程序,大到组成整个操作系统或者办公软件,小到打印一个九九乘法表,它们都有三个共同的功能块:

  • 计算
  • 流程控制
  • 输入输出

计算,不但是数学运算,也包括对语言文字信息的分析,判断异同、比较大小,都属于“计算”的范畴。如果没有计算,如果所有的数据、信息都不需要处理,我们要计算机做什么?当打字机使么?

流程控制,包括条件判断、循环、跳转。通过使用流程控制,我们可以写很短的程序,让计算机重重复复地执行成千上万的步骤,并且花样繁多。计算机虽然不会思考,但它们做明确具体的事情时还是比人速度快、而且重复性好。你让计算机做两个数相除,做一亿次的结果都是一样的,且它也不喊累。可让人来做的话,首先就是慢,也可能做错,做十次会不耐烦,做五百次会精神崩溃。小时候被老师罚抄作业十遍的同学,请自行默默回忆童年时的阴影。

输入:键盘、鼠标指令,从网络上接收服务请求,或者从硬盘读个图片……把外部设备上的电信号吸纳进计算机的过程,都算是输入。输出:在屏幕上显示一张图片、一些文字,往U盘上拷东西,播放音乐或视频……把计算机心里想明白的事情说出来的过程,这些都是输出。如果程序没有输入,那么它每次的运算都是从已知的、固定的条件开始,结果会单调得让人厌烦。学编程的时候,看到一群老年大专生用BASIC语言打印熊猫,以为自己在编程,心里的怜悯油然而生。如果程序没有输出,计算机有电没电的区别就不太大了,当然,冬天屋里冷的时候,多开个电器,确实可以更暖和一些。

可以说,所有的程序做的事情不外乎这三个概念。你打开网络浏览器,IE也好,FireFox也罢,你输入一个网址,按回车键,它就向网络端口上输出一个请求,向那个网址要网页,要来的网页从网络端口输入进来,浏览器反复判断每个传进来的数据流,看它们是图片还是一般文字,如果是图片,还需要做些解码工作计算摆放它们的位置,显示在窗口上。在这个回合里,计算、流程控制、输入输出都是齐全的。除了这三样,确实也没有其它的操作了。

说了这么多,我来演示三个例子吧。

第一个例子,是算从1加到100的总和,传说高斯用很聪明的办法搞定了这道题,我们来看看很笨很死脑筋、却擅长做高速计算的计算机是怎么做的。打开Python的窗口(说啥呢?),输入(虽然可以拷贝粘贴,但我更希望你亲自敲一遍):

total = 0
for i in range(1, 101):
	total = total + i
	# 请在这里多敲一两次回车(Enter)键,以使Python显示>>>提示符
print(total)

打字时请注意,Python对每行的缩进要求很严格,因为它认为这是表达程序结构的一部分,所以一定要按照这个例子里来敲。敲完最后一行“print(total)”,如果你看到了5050,就知道自己做对了。
猛击阅读全文

程序员入伙书——两个世界

作为程序员,我们常往来于两个世界之间:计算机世界和现实世界。为了快速地让你感受到这两个世界的不同,我举一个例子。请在Python(啥?)的“>>> ”提示符后输入这样一行:

int(0.7 / 0.1)

现在先不要按Enter(回车)键,停下来,听我解释一下:这句话意思是,计算0.7除以0.1所得的商,取其整数部分。这个简单的除法,你觉得结果会是什么?

7,对吧?现在,敲回车,看看计算机认为结果是什么。

>>> int(0.7 / 0.1)
6
>>>

😮 😮 😮

为了弄清楚这个6是怎么出来的,我们先把“取整数部分”去掉,只留下0.7 / 0.1——如果你曾经听说过“调试”这个词,我们现在就是在调试:

>>> 0.7 / 0.1
6.999999999999999
>>>

现在我们至少可以理解,为什么“取整数部分”之后的结果等于6了,因为6.999999999999999的整数部分确实等于6(虽然四舍五入等于7,但“取整数部分”的操作是比较憨傻的)。可是可是,为什么0.7 / 0.1不正好等于7呢?这就是计算机世界和现实世界的差别之一。完美的数学世界里,任意两个实数之间必然存在无穷个实数,而计算机不这么认为。因为计算机的位数有限,它能表达的实数是有限的,实数之间总是存在一个个“空隙”,在计算机的世界里,“两个相邻的实数”是合理的说法。不精确但是意思到了的类比是,在只能显示五个数字的计算器液晶屏上,刚刚比1.0000大的下一个数就是1.0001,而介于其间的其他数,如1.00005、1.0000342376,则无法被这个液晶屏精确表达。

说出来你可能不信,0.1就是一个计算机无法精确表达的数字。这个数字对于我们这些习惯了十进制的人来说,是如此的简洁。可是机器用二进制思考,在二进制的世界里,十进制的0.1是一个无限循环小数:0.000101000101…,无法被精确表示。

再考虑这段例子:

>>> 1e10
10000000000.0
>>> 1e10000
inf
>>> 

1e10的意思是1乘以10的10次方,计算机心领神会地把这个数字表达出来了。1e10000的意思是1乘以10的10000次方,计算机口吐白沫地说:这个数……太大了……这就是传说中的“无穷大”吧?
猛击阅读全文

程序员入伙书——下载Python并念诵程序员真言

想通过纯读书来学习任何技术,可能都行不通。我发现,即使你不编写程序,而只是把别人写好的程序亲自在键盘上敲一遍,都会有很强的感觉。默读一首诗,试图背诵它,不如念出声给自己听来得快。所以我恳请读者通过练习来掌握编程,练习需要用至少一种编程语言,我在这里推荐Python,后头的示例里,也会一直用Python来做例子。

你可以尽情忽略本篇里的“编程语言”、“Python”这些还不应该被提及的术语,它们目前一点也不重要。

对于早就是程序员的围观群众来说,我选择Python作为示范语言的理由有:

  • Python无需(看得见的)编译即可直接运行。
  • Python完全免费,拿来教学不涉及法律问题。
  • 使用Python的话,即使是初学者的程序,看起来也和牛人们写的一样悦目。(请呵呵大笑)

在Windows的机器上,下载并安装Python的步骤(其他机型需要去http://www.python.org自行发现):

  1. 点击 http://python.org/ftp/python/3.3.0/python-3.3.0.msi下载一个叫做python-3.3.0.msi的文件。把它存放在你的桌面上,或者一个你回头找得着的文件夹下。
  2. 下载完毕后,运行这个文件,接受一切默认选项,一路点Next就可以了。
  3. 安装完毕后,当你点“开始”或者“Start”按钮,再移动鼠标到“所有程序”或“All Programs”时,你会发现一个叫做“Python 3.3”的新建程序组,再移动鼠标到这里展开它,选择“IDLE (Python GUI)”,你会看到这个窗口:

当读者老爷们看到这个窗口后,我不想对大家说:“恭喜你!工具已经准备好了,现在请关掉窗口并期待明天的正式讲课。”正相反,我想请大家做一件十分重要、十分重要的事情。这个事情,就是念诵程序员真言,写下你人生中的第一个程序。让闪烁的光标伴随着你因激动而发抖的双手,在窗口提示的“>>> ”后面输入以下文字:

print('hello, world')

现在,停一下,请检查:

  • hello和world必须全都是小写字母。
  • world后面不要跟句点。
  • 逗号后面一定要跟个空格。

都确认之后,敲Enter键,你会看到窗口里有这些内容:

>>> print('hello, world')
hello, world
>>>

其中第一行print啥啥的是你敲进去的,第二行“hello, world”是程序的输出,而“>>> ”是Python期待你继续指挥它的提示符。

关于“hello, world”,传说,每个程序员必须尽早让自己的一个程序朗诵这句话,并且,除了朗诵这句话之外,这个程序什么别的事也不要做。念诵这句话必须做到每个字母、每个标点、每个空格都是精准正确的,否则,不但不能成为一个好的程序员,未来的编程工作中还会出现种种意想不到的失误(简称bug)。

现在,我可以说:恭喜你!欢迎入伙!你编写了至少一个程序,现在已经是程序员了!

程序员入伙书——序

公司里有个小女孩,在我组里工作一年半了。虽然在我组里,其实是挂靠一下。她的工作是数据录入,多是手工工作,体力上很辛苦,工资也委实不高。但她很敬业很努力,也时常做超越自己的事情。

我这个组里的其他人都是程序员,她坐在里头,耳濡目染地有了一些思路。每每有事,她还是很想用自动化的方法解决的。有这么一个机会,一个同事用Excel写了个数据发送程序,里面放了些用于统计及查错的公式,这还没涉及编程呢,已经引起她浓厚的兴趣。后来她还真的自己捣鼓出来一个检查数据是否已经完备的VBA,别管她请了多少人帮忙吧,总算是她自己推进的,更重要的是她做成了。我注解一下,在大公司里,做一件不同于常规业务职责的事,是很不容易的。

曾经有封信,从好吃懒做的印度同事发来的,信里问的是个技术问题,当时北京已经下了班,他们就把信发给了巴黎技术组的当班经理,不料这小姑娘当时在北京的办公室还没下班,就手把这个“技术问题”解决了。印度大窘,后来常常受到我们的挤兑:你们就不能多学点?你瞧瞧我们的小姑娘,也不是科班出身,才毕业一年多点,都不用技术员们帮忙就搞定了!

我觉得呢,很多事情,例如写程序,有些人说学不会,那是有两个原因:一、没兴趣;二、没法让他感兴趣。如果第一个原因是第二个原因引起的,或许还可以从表达手段上努力一下,拉他们入伙。像我刚才说到的这位小姑娘呢,她是感兴趣却还没有完全找到感觉,平时说话也总让人觉得糊里糊涂的。但我觉得,这个“糊里糊涂”只是非码农的经典思路而已,只要能上道,就可以改变。以我的表达水平,把她雕琢成程序员还是有希望的。人到我这里时一张白纸,如果被我画上画,而且还画得不错,拿出去能升值,是我最大的成就。

所以我准备写个编程教材系列,把只会使用“电脑”(对不起,我只称“计算机”)打字上网玩游戏的非科班人士变成程序员。不要指望读了这个系列能成为计算机科学家,因为我还不是。我也不想把这个教材称为傻瓜书,因为大家不傻。我本着平等的原则,称之为“程序员入伙书”吧。

辨识佛像——小测验

《辨识佛像》系列终于写完了,不知不觉间,写了四十八篇,涉及到七十一位尊胜。真高兴自己把一件事坚持做了下来。

读过这个系列的诸君,敢不敢测验一下? 🙂 开卷考试哦。如果还不是太有信心,可以点击这里温习一遍,通过点击菜单“展廊”……“辨识佛像”,也可以随时访问这个页面。

在这个小测验里,我选了十八幅佛像的图片,大家可以试着判断一下。如果实在猜不出来,把鼠标移到图片上方,会显出佛像的英文名和拍摄地点。如果从英文名还是猜不出来,可以点击图片看谜底。大多数图片来自北大赛克勒博物馆于2012年10月展出的瑞宝阁珍藏佛像。

















辨识佛像──拾遗(二)

毗瓦巴·首都博物馆

大成就者毗瓦巴的经典姿态,是自在而坐,须发鬈曲,以自信姿态手指天空。这个姿态,来自他以手指定住太阳抵押给酒馆的典故。

那若空行母

那若空行母·德格印经院

那若空行母的辨识特征有:弓箭步的威立姿,微微仰面向天,左手持嘎巴拉碗端至口边,右手执金刚钺刀,肩上横天杖一枝。

龙尊王如来·北大塞克勒所见

龙尊王如来是文殊师利菩萨早已成就的佛果,他的明显标识是背光里的七条龙。这些龙看起来是蛇形,实为印度教的那伽(Naga)龙族形象。

十二臂象鼻天·首都博物馆

大自在天的长子、象鼻天,其特征显而易见——长了个大象脑袋。正宗的象鼻天造像还有两个细节:一、右牙折断,因其写经文时笔被写秃,于是折断自己的牙继续写。二、手持一只萝卜,我并不确知这个“法器”的含义。

增长天王·首都博物馆

南方增长天王常以人间武士造型出现,辨认标识是手中的宝剑。另外三位天王的标识是:持国天王执琵琶,广目天王握龙(或曰蜃),多闻天王举幢。

黑财神·北大赛克勒所见

黑财神是五姓财神之一,全身裸体,性器显著,左展姿态威立,脚踏一持宝夜叉,右手托嘎巴拉碗,左手握吐宝兽作为其财神身份之标识。

松赞干布·《迎佛入藏图》唐卡局部

松赞干布被认为是观自在菩萨的化身,因此对他的造像的经典造型,是头顶丝冠(赞夏帽)里裹有红色阿弥陀如来小像一尊。松赞干布也被俗称为“双头王”,是指此意。

辨识佛像——拾遗(一)

人一懒下来,就很难勤快回去啊。早就打算写的《拾遗》,在草稿箱里沉睡了两个多月。

既然是拾遗,对于以下要提到的佛像,就不再一一细说了。把重要辨识特征点明,就会一带而过。如果想仔细了解,可以通过评论交流,或者自行搜索。

帝洛巴·辽宁博物馆

帝洛巴(或译帝诺巴)的重要标识是握在手中的鱼。凡人的眼中,他正在生吃这些鱼。而在寻访上师的那洛巴的眼中,他是在度化它们。摄影@博物致知

米拉日巴·见于赛克勒博物馆

米拉日巴尊者的独特姿态是手放耳畔,做倾听状。多放右耳边,左耳造型的也有。

宗喀巴大师·首都博物馆

宗喀巴大师的造型和文殊菩萨相同:双手说法印、经书、宝剑。但一般是僧人形象而非着天衣璎珞之报身相。

不空羂索·德格印经院

不空羂索是观自在菩萨的一种化现,简单的速记法就是“三面四臂观音”。如果只有一张面孔,则是经典的四臂观音造像。

叶衣佛母·首都博物馆

叶衣佛母的造像标识是其衣裙以枝叶构成,手中也常持树枝。

白哈尔·首都博物馆

白哈尔的身明王(骑狮子)和单坚护法极易混淆,但其他几位明王多不骑狮子不骑羊,就很容易认了。业明王虽然骑狮子,但头戴藤帽,三头六臂,张弓执箭,是辨认他的重要特征。

水天·首都博物馆

水天护法常侧骑摩羯或龙,摩羯只有双足立于地上,乍一看会让人觉得是他双腿夹着龙亲自站在地上,造型极易辨识。

《博物馆摄影技巧》被高度认可

以前我写过一篇《博物馆摄影实战技巧》,里头说:

  • 穿黑衣服。防止自己的影子反射到展品的玻璃罩上。
  • 最好再带一个穿黑衣服的人同去,那个人可以帮你遮挡背景光和纷乱的人群。 如果不妨碍旁边的观众,且不至于让管理员怀疑你在偷东西的话,黑衣服是可以脱下来罩住玻璃柜的。

今天看到一张照片,是七位博物馆达人参观国家博物馆的《复兴之路》展览时的合影。照片表明摄影技巧已被实践推行,获得高度认可。

七位博物馆达人身着黑衣参观国博《复兴之路》

一下带去这么多黑衣同好,遮光效果堪称伸手不见五指了。略感遗憾的是西装的大V领,里头的衬衫反光不可小觑。右三这位达人,穿黑衣服就可以了,不用抹黑脸蛋涂黑眼圈的。