优雅编程

程序优化方法

优化需要通过大量测试来验证一致性、性能,因为并非所有优化都是正确或必要的。从重构程序执行流的角度来讲,优化并不是灵丹妙药,并在不同语言、不同编译器、不同环境、不同任务中表现出巨大的差异。以下的优化方法均仅供参考。

利用短路与哨兵

  • 将出现频率高的情况放在优先执行的位置
  • 循环中,搜索到目标后立即退出循环
  • 循环搜索时,也可以将搜索对象放在数组最后(额外空间),最后检查下标。(本质上是保证不会越界搜索,且保证循环一定正确结束)

优化计算效率

  • 程序执行前计算结果,通过常量保存、硬编码、文件保存的方法来避免重复计算
  • 尽量减少循环体内的计算工作,可以在之前计算完毕并保存,之后引用
  • 公共子表达式应当保存在变量里
  • 适当将乘法重写为加法、幂重写为乘法、整数代替浮点数、单精度代替双精度、移位操作代替乘除2、三角恒等式代替三角函数
  • 尽量减少数组维度与数组引用
  • 多重循环时,将循环次数少的放外层

使用低级语言重写代码

  1. 使用高级语言完成程序编写
  2. 进行测试,验证正确性
  3. 进行程序分析,确定热点代码
  4. 对热点代码使用低级语言改写

设计恰当的执行控制流

循环

  • 循环层数最好不要超过三层
  • 短循环可以多使用break、continue等控制,长循环尽量保证唯一出口
  • 循环附近不要写重复的代码(修改需要同步修改多处,不便维护)
  • for适合与“数量”有关的循环,且不要在内部修改下标;while适合与“条件”有关的循环
  • 循环体应当自成子程序,循环条件应当清晰易读
  • 多使用for循环,但不要把与循环无关的语句(比如初始化一个不用于循环的变量)放在循环头
  • 不要写空循环,将空循环改写成while循环
  • 如果一个循环可以做两件事情,把它们拆成两个循环,除非注明在性能上有所提高
  • 不要将循环下标作为结果返回。如果需要使用,可以在循环开始前定义新的变量,然后在循环内部对这一变量进行赋值

建表,以提高代码质量

用查表法替换繁琐的if-else判断

使用大量if-else的坏处:

  • 不易阅读
  • 代码重复度高,无意义
  • 对于复杂情况,容易漏条件
  • 判断逻辑硬编码在代码中,维护不便

使用查表法的好处:

  • 易读
  • 代码简洁且高效
  • 不会漏掉条件
  • 可以将表放在外部文件或者统一放在一起,便于维护;可以在不改变程序的情况下修正运行结果

用法:将要判断的各个参数作为表的维度,将判断结果作为表索引后的结果。

用索引表替换数据表

稀疏的数据表在存储对齐的情况下会浪费大量空间。与之相比,采用索引表可以降低空间浪费量(仍然会产生浪费)。为了进一步减少索引表空间,可以使用阶梯索引表,根据数据的范围(而不是具体的数据值)进行建索引,比如根据百分制成绩计算绩点,建立相应的data-to-key函数,放在数组中。

用结果表替换数学计算结果

考虑到系统函数的精确性,计算速度可能较慢。可以预先手动算出一些数据并建表,计算时直接查表即可,大大提高程序性能。