剑指Offer学习总结-数值的整数次方

剑指Offer学习总结-数值的整数次方

本系列为剑指Offer学习总结,主要是代码案例的分析和实现:
书籍链接:http://product.dangdang.com/24242724.html
原作者博客:http://zhedahht.blog.163.com/blog/static/254111742011101624433132/
原作者博客链接有完整的项目代码下载。


数值的整数次方

题目

题目:实现函数 double Power(double base,int exponent), 求 base的exponent 次方不得使用库函数, 同时不需要考虑大数问题。C++中这个函数参数的限制是base不能为负数,并且exponent不能为小数。

第一眼看到的解法:

看到题目的第一思路,我们直接使用一个循环利用乘法给base计算exponent次,
使用一个变量来迭代结果数值,初值为1

double Power(double base, int exponent)
{
    double result = 1.0;
    for(int i = 1; i <= exponent;++i)
        result *= base;
    return result;
}

我们使用简单的数据测试一下即可发现问题,exponent是整数类型,整数可能有整数负数和零。
当我们使用负指数的时候,我们需要将底数求倒数,然后利用指数的绝对值进行叠加,显然这个情况没有考虑。
当指数为0,底数不为0的时候,结果是1。
底数为0,指数也为0,没有实际意义,因此无论是输出 0 还是 1 都是可以接受的。
上边的方式只适用于指数是无符号的类型。

考虑全面的解法:

double Power(double base, int exponent)
{
    //我们釆用全局变量来标识是否出错  我们在外界来判断参数和返回值是否是合法的
    g_InvalidInput = false;
    //考虑 底数是否为0  由于double类型有精度误差  我们不能用==来判断,是否相等,使用equal(实现是判断差值的绝对值在很小的范围内算做等于)
    if(equal(base, 0.0) && exponent < 0)
    {
        g_InvalidInput = true;
        return 0.0;
    }
    //当无符号数(int)和有符号数(unsignedint)进行算数运算时,有符号数(int)会先转换为无符号数(unsignedint),
    //用补码来表示 再进行相应的算数运算。 是内存中一次存储格式的转换
    unsigned int absExponent = (unsigned int)(exponent);
    //如果是小于0的指数 ,将原数据取负变正  在进行赋值
    if(exponent < 0)
        absExponent = (unsigned int)(-exponent);

    double result = PowerWithUnsignedExponent(base, absExponent);
    //如果是小于0的指数 将结果取倒数
    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;
}
//判断是否两个double类型的数值相等
bool equal(double num1, double num2)
{
    if((num1 - num2 > -0.0000001)
        && (num1 - num2 < 0.0000001))
        return true;
    else
        return false;
}

优化性能的解法:

如果我们碰到的面试官是一个在效率上追求完美的人, 那么他有可能
会提醒我们函数 PowerWithUnsignedExponent 还有更快的办法。
计算提高效率的部分,我们可以发现一个数学规律。

an={an/2an/2,a(n1)/2a(n1)/2a,nn

这个公式很容易用递归来实现。隐藏的终止条件是 指数为1,返回值是底数本身。

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;
}

你可能感兴趣的:(算法分析)