论程序设计方法


  论程序设计方法
  http://tech.163.com/school · 2005-04-04 22:28:23 · 来源: vckbase
  
    如果你是初学者----------------请不要阅读;
     但有志成为中高级程序员--------请务必阅读;
     如果你是中级程序员------------请务必阅读;
     如果你高级程序员--------------请批评指正。
  
  
     本文是我在“软件工程师班”开学第一节课的讲义,和“计算机软件设计发展”讲座
  上的内容整理而成。写作本文的目的是引导学生从更高的层次来看待程序设计方法,为将来
  成为高级程序员而做好理论准备。
  
    一、计算机硬件环境对软件设计方法的限制
  
     计算机的发明到现在已经60年了,计算机程序设计方法也伴随着计算机硬件技术的提
  高而不断发展。硬件环境对软件设计既有严重的制约作用,也有积极的推动作用。
  
    
  在我的大学母校(此处删除6个字),数学系的一些老师,有幸成为了我国第一代的计算机
  DIY一族。呵呵,不要以为是组装PC机呦,他们组装的可是小型机。一人多高铁皮柜大小的
  主机,加上纸带机(后期改进为读卡机),组装好后,除了供学校自己的科研使用外,还在
  全国各地销售了十
  几台。当时(七十年代)一台的售价是10几万元人民币,如果换算到今天,相当于价值大约
  为100多万元,非常高档的小型计算机了。下面大家猜猜,这么高档的计算机,它的内存是
  多少那?(都把嘴闭好了,我要公布答案了)—— 4K。
  
     一块50公分见方的内存板,
  
     插入到主机箱中,好了------ 1K;
     再插一块内存板,好了------ 2K;
     再插一块内存板,好了------ 3K;
     再插一块内存板,好了------ 4K;
     再......不行了,插不起了,太贵了!这就是当时的环境。这样的环境下,用什么写
  程序那?当然只有机器码了。先用汇编写,然后翻阅手册手工改写为机器码,然后打卡或穿
  纸带,输入运行。可以想象,在当时的条件下,什么叫好的程序那?什么叫优秀的程序那?
  —— 技巧!
  
     程序设计的最初始阶段,是讲究技巧的年代。如何能节省一个字节,如何能提高程序
  运行的效率,这些都是要严肃考虑的问题。而所谓的程序的易读性,程序的可维护性根本不
  在考虑范围之内。
  
     今天,35岁以上的学习过计算机的朋友可能都使用过一种个人计算机——APPLE-II(
  中国也生产过这种计算机的类似产品“中华学习机”)。主频1M,内存48K(扩展后,最多
  可达到64K)。我就是使用这样的计算机长大的
  :)。当年,类似的个人计算机产品,还有PC1500,Layser310等。这种计算机上已经固化了
  BASIC 语言,当然只是为学习使用。要想开发出真正的商业程序,则必须使用汇编,否则的
  话,程序就比蜗牛还要慢了。于是,程序设计中对于技巧的运用,是至关重要的了。
  
     题外话1:
  
     比尔盖茨是 BASIC 的忠实拥护和推动者。当年,他在没有调式环境的状况下,用汇编
  语言写出了一款仅有 4K 大小的 BASIC 解释器,且一次通过。确实另人佩服。(不象现在
  微软出品的程序,动辄几十兆。)这也许就是比尔对 BASIC
  情有独忠的原因,每当微软推出(临摹)一个新技术,则他会立刻在 BASIC 中提供支持。
  
     题外话2:
  
     在 APPLE-II 上有一款游戏软件“警察抓小偷”,当年熬夜玩游戏,乐趣无穷。后来
  这款游戏被移植到了PC上,咳~~~根本没有办法玩,因为小偷还没跑就被警察抓到了。硬件
  的速度提升,另我无法再回味以前的时光了。
  
    二、结构化程序设计
  
     随着计算机的价格不断下降,硬件环境不断改善,运行速度不断提升。程序越写越大
  ,功能越来越强,讲究技巧的程序设计方法已经不能适应需求了。记得是哪本书上讲过,一
  个软件的开发成本是由:程序设计 30% 和程序维护 70%
  构成。这是书上给出的一个理论值,但实际上,从我十几年的工作经验中,我得到的体会是
  :程序设计占 10%,而维护要占 90%。也许我说的还是太保守了,维护的成本还应该再提高
  。下面这个程序,提供了两种设计方案,大家看看哪个更好一些那?
  
     题目:对一个数组中的100个元素,从小到大排序并显示输出。(BASIC)
  
     方法1:冒泡法排序,同时输出。
  
  FOR I=1 TO 100
    FOR J=I+1 TO 100
     IF A[I] > A[J] THEN T=A[J]: A[J]=A[I]: A[I]=T
    NEXT J
    ? A[I]
  NEXT I
     方法2:冒泡法排序,然后再输出。
  
  FOR I=1 TO 100
  FOR J=I+1 TO 100
  IF A[I] > A[J] THEN T=A[J]: A[J]=A[I]: A[I]=T
  NEXT
  NEXT
  
  FOR I=1 TO 100
  ? A[I]
  NEXT
  
    
  显然,“方法1”比“方法2”的效率要高,运行的更快。但是,从现在的程序设计角度来看
  ,“方法2”更高级。原因很简单:(1)功能模块分割清晰——易读;(2)也是最重要的
  ——易维护。程序在设计阶段的时候,就要考虑以后的维护问题。比如现在是实现了在屏幕
  上的输出,也许
  将来某一天,你要修改程序,输出到打印机上、输出到绘图仪上;也许将来某一天,你学习
  了一个新的高级的排序方法,由“冒泡法”改进为“快速排序”、“堆排序”。那么在“方
  法2”的基础上进行修改,是不是就更简单了,更容易了?!这种把功能模块分离的程序设
  计方法,就叫“
  结构化程序设计”。 
  
  三、对程序设计中技巧使用的思考
  
     我可以肯定,大家在开始学习程序设计的时候,一定都做过这样一个题目:求100以内
  的素数。老师在黑板上,眉飞色舞地写出了第一个程序:(C程序)
  
     方法1:
  
  for(i=1; i<100; i++)
  {
    for(j=2; j< i; j++)
     if(i%j == 0) break;
     if(j >= i) printf("%d,", i);
  }
     然后,老师开始批判这个程序“这个叫什么呀?太慢了!因为我们都知道大偶数不可
  能是素数了,因此,要排除掉!” 于是,意尤未尽地写出了第二个程序:
  
     方法2:
  
  printf("2,");
  for(i=3; i<100; i+=2)
  {
    for(j=2; j< i; j++)
     if(i%j == 0) break;
     if(j >= i) printf("%d,", i);
  }
     老师说:“看!我们只改动了一点点,程序运行的速度就提高了一倍多”。然后运用
  诱导式教学法继续提问“程序的效率,还能再提高吗?能!”,得意地写出第三个程序:
  
     方法3:
  
  printf("2,");
  for(i=3; i<100; i+=2) ''不考虑大偶数
  {
    for(j=3; j< i/2; j+=2) ''不考虑用偶数去测试,而且只验算到一半就足够了
     if(i%j == 0) break;
     if(j >= i) printf("%d,", i);
  }
     “大家看,我们又只改动了一点点,运行速度又提高了一倍多。可以了吗?不可以!
  我们还能再提高”。于是又高傲地写出了第四个程序:
  
     方法4:
  
  printf("2,");
  for(i=3; i<100; i+=2)
  {
    int k = sqrt(i);
    for(j=3; j<= k; j+=2)
     if(i%j == 0) break;
     if(j >= k ) printf("%d", i);
  }
     然后,开始证明为什么我们判断素数的时候,只需要验算到平方根就足够了:
  
     假设p是合数,那么令:p=a*b。反正法:由于我们已经判断了p的平方根以内的整数都
  不能被p整除,于是 a>SQRT(p)。基于同样的理由 b>SQRT(p)。于是 p = a * b > SQRT(p)
  * SQRT(p) = p 得出矛盾, 命题得正。
  
     的确,“方法4”的确比“方法1”的运行速度要提高了好几倍,甚至好几十倍。但我
  们仔细分析测试看看。
  
     (1)“程序4”到底比“程序1”快了多少那?我在某台计算机上进行测试(P4,
  1.5G)得到的速度对比表:
  
  计算范围 100 1000 10000 100000
  速度差 0.00秒 0.01秒 0.18秒 15秒
    
     (2) 在10万以上,才会看出一些差别。而这种差别根本就不够底偿程序设计阶段的
  付出。如果计算的范围再大,那么不管是“方法1”,还是“方法4”都不是好的算法。(计
  算素数的另外一个比较优秀的算法叫“漏筛法”)
  
     (3)写出“方法1”,只要具有小学四年级的数学水平就够了,而“方法4”则需要初
  中三年级的水平并且还要具备一些“数论”的知识。
  
     (4)从维护性看,如果你写的程序需要另外一个程序员来维护,或者若干时间以后,
  你重新来阅读这段程序,那么就会对这个程序产生很多疑问:这个求平方根是干什么用的?
  其实,就这个题目来说,使用到“方法3”就已经足够了。
  
     总结发言:
  
     I. 计算机的价格每年下降一半,而运算速度每年提高一倍”,因此我们应该把速度提
  高的任务交给硬件实现。
  
     II. 从易读性、维护性出发,程序员只负责按定义给出软件实现。算法的问题是数学
  家解决的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值