前言
本文记录一些有助于提高代码性能和平时一些难以想到的细节处理
正文
一. 边界值
1.1 基本类型的范围限制
一般而言, 看到基本类型, 特别是返回值或者涉及到计算的, 都应该考虑基本类型的范围限制
- 比如实现库函数:
double Pow(double base, double exp)
时, 需要考虑大数问题(如果要求是任意大的数字, 则需要使用特殊的数据结构来表示数据, 比如用字符串或者数组来表示大的数字, 以确保不会溢出(这也是大数问题的解决方法))
二. 性能
性能的影响一般分为时间性能和空间性能, 一般性能的提升考虑的方面有: 递归转循环, 位运算代替加减乘除, 算法改进(如: 利用全局有序或者局部有序使用二分等)
2.1 快速计算乘方
计算
- 公式如下
- 除了使用常规方法, 即一个n次循环计算乘方外, 可利用上面的公式来快速计算; 该公式是明显的递归式
double PowerWithUnsignedExponent(double base, unsigned int exponent) // 注意
{
if (0 == exponent)
return 1;
if (1 == exponent)
return base;
double result = PowerWithUnsignedExponent(base, exponent >> 1); // 注意
result *= result;
if (1 == exponent & 0x1) // 注意
result *= base;
return result;
}
- 上面的代码中需要注意的几点
- 使用
unsigned
来进一步限定范围 - 判等时, 常量放在左边
- 使用移位运算代替乘除
- 使用与运算代替奇数和偶数判断
- 使用
2.2 位运算
2.2-1 奇偶判断
奇数二进制最后一位为1, 可利用与运算判断
if (1 == target & 0x1)
{
// 奇数...
}
else
{
// 偶数...
}
2.2-2 位移运算代替乘除
- 左移
<<
一位, 相当于乘2; 右移>>
一位, 相当于除以2 - 注意移位规则
- 左移: 右边直接补充0
- 右移: 如果是一个无符号数, 左边用0填充n位; 如果是有符号数, 左边使用其符号位填充n位
三. 编码细节
记录一些常见或者很隐晦的编码错误或陋习
3.1 浮点数的相等判断
- 不可直接使用
a == b
的形式判断, 因为计算机表示浮点数是无限循环小数, 但是float和double是有限的, 结果就会差那么一点点; 具体参见回答; 所以一般会将浮点数的判等转换为<=
或者>=
, 即如下重写一个equals()
函数; 同时需要注意的是当用浮点常量和浮点变量相比较时, 不要忘了还是应该用这种比较噢
int equals(double a, double b)
{
return fabs(a - b) < exp; // 其中exp为精度(如: 0.000001), 需要具体讨论得出
}