剑指offer-面试题11:数值的整数次方

这一节还是挺有收获的,作者首先讲了代码的规范性和完整性。规范性即清晰地书写、清晰的布局、合理的命名,我想这也是对一个优秀的程序员的基本要求。代码的完整性里面提到了几个以前没听说过的概念。确保代码完整性的3个方面:功能测试边界测试负面测试

功能测试即考虑普通功能的测试用例,写出的代码要能够满足面试官要求的基本功能,同时考虑问题要全面,不能遗漏。边界测试即程序中可能存在递归和循环。如果是循环,那么结束循环的边界条件是否正确。如果是递归,递归终止的边界值是否正确。最后还要考虑各种可能的错误输入,也就是通常所说的负面测试用例。

3种处理错误的方法:

1.返回值。函数用返回值来告知调用者是否出错,这种方式的缺陷是不能通过返回值直接调用函数的计算结果,因为返回值被占用。

2.全局变量。这种方式可以通过返回值直接调用函数的计算结果,但缺点是很容易忘记去检查全局变量。

3.异常。当函数运行出错的时候,我们就抛出一个异常,我们还可以根据不同的出错原因定义不同的异常类型。缺点就是有些语言不支持异常,抛出异常时对性能有负面影响。

下面以一个题目来作为实例:

实现函数double Power(double base, int exponent),求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。

解答:最忌讳的是只考虑到指数是正整数的情况,指数还可以是0,负数。如果是指数是负数,直接求正数次幂然后求倒数就可以了,但是需要注意0不能求倒数,这里需要返回一个异常。

bool InvalidInput = false;

double PowerOfUnsignedExp(double base, int exponent)
{
    if(exponent == 0)
        return 1;
    if(exponent == 1)
        return base;
    
    int HalfExp = exponent >> 1;
    double result = PowerOfUnsignedExp(base, HalfExp);
    result *= result;
    if(exponent & 1 == 1)
        result *= base;
    return result;
}

bool equal(double num1, double num2)
{
    if((num1 - num2 > -0.0000001) && (num1 - num2 < 0.0000001))
        return true;
    else
        return false;
}

double Power(double base, int exponent)
{
    if(equal(base, 0.0) && exponent < 0)
    {
        InvalidInput = true;
        return 0.0;
    }
    
    unsigned int UnsignedExp = (unsigned int)exponent;
    if(exponent < 0)
        UnsignedExp = (unsigned int)(-exponent);
    double result = PowerOfUnsignedExp(base, UnsignedExp);
    
    return (exponent < 0 ? 1.0/result : result);
}
代码里用到了两个技巧: 用右移运算符代替了除以2,用位与运算符代替了求余运算符来判断一个数是奇数还是偶数。位运算的效率比乘除法以及求余运算的效率高得多。

你可能感兴趣的:(剑指offer-面试题11:数值的整数次方)