按 ‘ 程序员 ’ 标签归档

程序员入伙书——简单数据

一边写一边问读者对这个系列教材的感觉。组里的小姑娘说,读下来,照着做,目前理解上没问题。不过她也说,她的室友是学新闻的,对编程不感兴趣,读这些文章时,反映“读不太懂”。她又说,直到现在还上开胃菜,进度有点慢,希望尽快吃到正餐。

好,正餐来了。

在《程序在干什么?》一章,我说过程序最基本的功能是计算——如果没有计算,我们也不需要计算机了。计算机的运算和人类的数学不同。人类的数学可以设置未知数,然后用推导方法把这个未知数的实际值逼出来。计算机的每一步运算,参与者都是已知的,只是有些参与运算的值永远不变,有些一会儿装三个苹果,一会儿装一百个大象。永远不变的被称为“常量”,可能改变的被称为“变量”。

以下我要说到的规则,仅保证对Python语言有效,其他语言虽然会很相似,但可能有自己的特色法则。

常量

有基本的两种常量:数字和字符串。快捷地描述它们的区别:数字是数学,字符串是语文。

数字很直接,0、-3.5、2012、378.2452,这些数学上看着顺眼的,都是Python语言里合法的数字。另外有些不太顺眼的数字,例如.3和5.,Python也宽宏大量地认为它们是合法的数字,.3意思就是0.3,而5.意思就是5.0。有些巨大的数字或者极小的数字,用科学计数法表达更为便捷的,如1.5×109或者3.0×10-32,Python不会让你辛辛苦苦埋头去数0,而是可以分别表示为1.5E9和3.0E-32,这里的E可以小写。指数前也可以加正负号。
猛击阅读全文

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

下载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,别管她请了多少人帮忙吧,总算是她自己推进的,更重要的是她做成了。我注解一下,在大公司里,做一件不同于常规业务职责的事,是很不容易的。

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

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

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