代码的规范性:(1)清晰的书写(2)清晰的布局(3)合理的命名
代码的完整性:(1)功能测试(2)边界测试(3)负面测试(性能测试、非法测试)
例如:把字符串转换成正整数时,基本的功能测试应包括零、正数和负数三种情况。“打印1到最大的n位数”,应注意大数溢出问题。
常见的错误处理方法:
| 优点 | 缺点 |
返回值 | 和系统API一致 | 不能方便地使用计算结果 |
全局变量 | 能够方便地使用计算结果 | 用户可能会忘记检查全局变量 |
异常 | 可以为不同的出错原因定义不同异常类型,逻辑清晰明了 | 有些语言不支持异常,抛出异常时对性能有负面影响 |
面试题11:数值的整数次方
题目:实现函数double Power(double base, int exponent),求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。
解法:先对指数求绝对值,然后算出次方的结果后再取倒数。同时应考虑分母为零的情况,当分母为零要做错误处理。
bool g_InvalidInput = false;
double Power(double base, int exponent){
g_InvalidInput = false;
if(equal(base, 0.0) && exponent < 0){
g_InvalidInput = true;
return 0.0;
}
unsigned int absExponent = (unsigned int)(exponent);
if(exponent < 0)
absExponent = (unsigned int)(-exponent);
double result = PowerWithUnsignedExponent(base, absExponent);
if(exponent < 0)
result = 1.0 / result;
return result;
}
double PowerWithUnsignedExponent(double base, unsigned int exponent){
double result = 1.0;
for(int i = 1; i <= exponent; ++i)
result *= base;
return result;
}
bool equal(double num1, double num2){
if((num1 - num2 > -0.0000001) && (num1 - num2 < 0.0000001))
return true;
else
return false;
}
由于计算机表示小数(包括float和double型小数)都有误差,我们不能直接用等号(==)判断两个小数是否相等。如果两个小数的差的绝对值很小,比如小于0.0000001,就可以认为它们相等。
解法优化:
如果输入的指数exponent为32,我们在函数PowerWithUnsignedExponent的循环中需要做31次乘法。假设我们的目标是求出一个数字的32次方,如果我们已经知道了它的16次方,那么只要在16次方的基础上再平方一次就可以了。而16次方是在8次方的平方。以此类推,我们求32次方只需要5次乘法:先求平方,在平方的基础上求4次方,在4次方的基础上求8次方,在8次方的基础上求16次方,最后在16次方的基础上求32次方。
a^n = {a^(n/2)*a^(n/2) n为偶数 a^[(n-1)/2] * [a^(n-1)/2]*a n为奇数}
double PowerWithUnsignedExponent(double base, unsigned int exponent){
if(exponent == 0)
return 1;
if(exponent == 1)
return base;
double result = PowerWithUnsignedExponent(base, exponent >> 1);
result *= result;
if(exponent & 0x1 == 1)
result *= base;
return result;
}
右移运算符代替除以2,用位与运算符代替求余运算符(%)
测试用例:把底数和指数分别设为正数、负数和零