海畔 夕阳隐去 白帆升起 海水写不完想念 晚歌唱尽忧伤 守候海畔 面向北风 那岸褪色的家园 椰风裹挟思乡 流连海畔 水花轻盈 故事随涛声远逝 明朝潮起何方 (原载于五月十六日给忱的信)
About Me
-
Recent Posts
Categories
Tag Cloud
Archives
海畔 夕阳隐去 白帆升起 海水写不完想念 晚歌唱尽忧伤 守候海畔 面向北风 那岸褪色的家园 椰风裹挟思乡 流连海畔 水花轻盈 故事随涛声远逝 明朝潮起何方 (原载于五月十六日给忱的信)
煎蛋:http://jandan.net/,当我打算看点儿东西用来放松时的首选方式。 草莓周刊:http://memedia.cn/,反正我觉得真是很好看。 那吒Anothr:http://anothr.com/,我目前最喜欢的RSS解决方案。(我的页面:http://anothr.com/tianyi。) 还有一些“非法”甚至“反动”的,就不说了。
第23章 调试本身并不是改进代码质量的方法,可以认为它只是一种补救措施、不得已的手段。在OI中应该尽量避免调试,应该在一开始避免错误的发生。调试的效率在人与人之间有巨大差距,所以培养调试能力十分有必要。 寻找缺陷和理解缺陷是调试中最费时的步骤。事实上在这点上不应该吝惜时间,一定要确保已经完全理解缺陷后再开始动手修改。 把需要尝试的事情在纸上逐条列出,这也许是一个加速调试得好途径,因为调试时的人大多都昏头昏脑的,最好有一个能让你保持清醒的东西。 优先检查最近修改过的代码。尽量对程序保持全局理解。永远不要随机地、尝试地修改代码,每一处代码改动都需要有明确的理由。一次只做一个改动。 心理因素让人看到他“希望”看到的东西,这对调试的影响有点大,所以要保持优秀且一致的编程习惯,要让变量名之间的“心理距离”尽量远。 把编译器警告级别设为最高,这是默认的。Profiler也可以当作调试工具,有时从不正常的运行时间或调用次数中可以看出错误。 第24章 一帆风顺的软件项目是神话,实际中的代码是经常需要经受剧烈变化的。好在实际中引起变化的(最?)重要原因——需求的变化——在我们的OI中不会出现,只要你别读错题了。 软件演化的基本准则是,演化应当提升程序的内在质量。 重构的定义是“在不改变软件外部行为的前提下,对其内部结构进行改变,使之更容易理解并便于修改”。需要重构的理由在OI中同样充分的有:代码重复,冗长的子程序,嵌套过深,过长的参数列表,命名不当。 特定的重构方法很多,也很系统,但在OI中还是应该尽量在一开始就写出更好的代码,毕竟你没有太多时间。 如果确定要对代码——特别是正确(指不可能WA)的代码——进行某种大幅度的修改(不一定是重构),一定先备份一下。 第25章 性能调整在OI中也许没有你一开始想象得那么重要,似乎复杂度才更王道。任何情况下“性能”都不是头等大事,正确性才是。 程序需求方面,就是可能不切实际的复杂度分析,少数时候实际运行时间无法用理论复杂度衡量。程序的设计就是基本的算法了,如果这里面出了致命问题,再多的代码调整也无济于事。最后的手段才是代码调整。 代码调整的问题在于,高效的代码并不一定就是“更好”的代码。80/20法则是一定要注意的,Profile一下嘛……“随时随地”的优化是绝对不可取的。 常见操作的相对效率那个表真是好东西。它说我们整数的赋值、整数的加减乘、浮点数的加减乘、调用一个函数、用下标访问数组等操作所需的时间都相差无几!这还真是惊人的结论……(有空还是自己验证一下。) 优化前,一定要保存代码的可运行版本。 第26章 OI中可以考虑的代码调整技术:用查询表替代复杂表达式(没用过呢还)、使用惰性求值(常用的思想);展开(这个很有点意思)、哨兵值(这个我比较喜欢)、把最忙的循环放在最里层(可能被忽视的常识)、削减强度(值得注意);尽量减少数组引用、使用缓存机制(事实上很高级的东西,值得简单地尝试);利用代数恒等式(如果真的有而你没发现的话……)、削弱运算强度(常用的)、使用正确的常量类型(以前没有注意过,也许真的很重要)、删除公共子表达式(为了程序清晰也应该做);把子程序写成内联(“现代”计算机说这样做不一定就会性能提升)。
昨晚临睡的时候我在想:此刻的你应该正在给我写信吧,明天是值得期待的一天,因为能收到你的信,因为能在令人窒息的代码海洋中看到一束透入水底的清新阳光。 今天,它果然如约而至了,如一片美丽的绿叶飞落在我的胸前,又如夜路中的一盏烛,细小而温暖的光点亮暗淡的远方。 收到你信的每天就是我的节日,是你让我的生活变得与从前那样不同。
第19章 在表明bool值的时候,应该采用true和false而非1或0。如果从“理论”的方面论述这一点,可以说1和0是“神秘数”而true和false就不是。 比较长的判断语句中的bool表达式是一个容易出错的地方。在bool表达式方面降低复杂度的方法有:把它提炼到一个函数里然后忘掉它、试图用DeMorgan律简化它、用括号使它更清晰。 要理解很多语言中对于&&和||运算都有“短路求值”的处理,如果想避免它可以使用&和|。 按照数轴的顺序编写数值表达式,也就是说写MIN<i&&i<MAX而非i>MIN&&i<MAX。 在写复合语句时先写好开头和末尾的大括号,再填充内容。一种良好的习惯是将if、for后面跟的一条语句也放到一个单独的块里。 在程序中要避免三四层以上的深层嵌套,因为他们带来可能不必要的思维复杂度。可以考虑的解决方法有:重复判断一部分条件(违反DRY原则,故似乎不大可取);重构某些代码到子程序中(这个比较好);使用break语句的小trick;试图转化为一组if-else-if语句。 结构化编程就是仅仅是用顺序、选择、迭代三种控制结构的编程方法学。控制流是复杂度来源的很大一个方面。度量(思维)复杂度有一种简单的方法,但在OI中大多时候是没必要这样度量的。 第20章 软件质量的特性中有很多是与OI无关的,外在特征中也就正确性和效率需要注意,内在特征几乎都不用过多考虑。软件工程学之所以存在,很大程度上就是因为这些特征是互相矛盾的。 有时靠阅读和检查代码发现错误会比测试高效得多,极限编程(XP)的结对编程和代码检查是降低出错率的重要手段。在OI中不妨借鉴这一点,当发现错误时,先不忙着调试,先把代码看一遍。但是这样做的前提似乎是代码风格应该足够优秀,能被轻松地理解,甚至能被速读。 第21章 协同构建这部分内容,或许ACM/ICPC选手可以从中得到启迪,但对于目前的OI还是一点用途都没有。 第22章 测试在OI中最主要的体现是自己编些数据来测试正确性,这比较接近于集成测试。但与单元测试的思想类似的方法似乎也是应该应用的,也就是在编写完一个感觉上很易错的模块时应该马上独立地测试它。