剑指offer--数值的整数次方

记录来自《剑指offer》上的算法题。

题目描述:

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

下面是一种解法:

// 判断num1是否等于num2
bool equal(double num1, double num2){
    if ((num1 - num2) > -0.0000001
        && (num1 - num2) < 0.0000001)
        return true;
    else
        return false;
}
// 求指数是正数的结果
double PowerWithUnsignedExponent(double base, unsigned int exponent){
    double result = 1.0;
    for (int i = 1; i <= exponent; i++)
        result *= base;

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

上述解法中使用一个全局变量g_InvalidInput,用来判断是否输入非法的输入,如输入的基数是0,指数是负数,那么就是一个非法输入。这里判断两个小数是否相等,只能判断它们之差的绝对值是否小于某个数,而这也是上述解法中定义函数equal()的原因,用来判断输入的数是否为0。

上述解法中,函数PowerWithUnsignedExponent()还可以进一步进行优化,因为该函数的循环次数等于输入的指数减一,如输入指数是32,则循环中的乘法要做31次,采用下述公式对求a的n次方进行优化:

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

其代码如下:

// 改进版本
double PowerWithUnsignedExponentOptimz(double base, unsigned int exponent){
    if (exponent == 0)
        return 0;
    if (exponent == 1)
        return base;

    double result = PowerWithUnsignedExponentOptimz(base, exponent >> 1);
    result *= result;
    if (exponent & 0x1 == 1)
        // 如果指数是奇数
        result *= base;

    return result;
}

这个代码是采用了递归方法来实现上述公式,同时采用位与运算代替求余运算(%)来判断一个数是否奇数还是偶数,这是因为位运算的效率比乘除法及求余运算的效率要更高。

测试例子可以查看我的Github。

你可能感兴趣的:(c++,算法,算法)