您的位置:首页 > Web前端

剑指Offer--011-数值的整数次方

2016-04-11 16:50 399 查看

链接

牛客OJ:数值的整数次方

九度OJ:http://ac.jobdu.com/problem.php?pid=1514

GitHub代码: 011-数值的整数次方

CSDN题解:剑指Offer–011-数值的整数次方

牛客OJ九度OJCSDN题解GitHub代码
数值的整数次方1514-数值的整数次方剑指Offer–011-数值的整数次方011-数值的整数次方
您也可以选择回到目录-剑指Offer–题集目录索引

题意

题目描述

给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。

自以为很简单的解法

class Solution
{
public:
double Power(double base, int exponent)
{
double res = 1;
for(int i = 0; i < exponent; i++)
{
res *= base;
}

return res;
}
};


貌似我们已经完美的解决了问题,但是真的这样么?

我们输入一个指数为负数的情况

Solution solu;
cout <<solu.Power(2, -3) <<endl;


可见我们的算法是多么的自以为是啊?

简单的处理边界的情况(全面但是不够高效)

前面所说的指数为负数只是边界的一种情况,学习算法,必须全面了解所有的边界

指数幂的所有边界包括

指数为0的情况,不管底数是多少都应该是1

指数为负数的情况,求出的应该是其倒数幂的倒数

指数为负数的情况下,底数不能为0

#include <iostream>
#include <cmath>
using namespace std;

//  调试开关
#define __tmain main

#ifdef __tmain

#define debug cout

#else

#define debug 0 && cout

#endif // __tmain

class Solution
{
public:
double Power(double base, int exponent)
{
//  指数为0的情况,不管底数是多少都应该是0
if(exponent == 0)
{
return 1.0;
}
//  指数为负数的情况下,底数不能为0
if(Equal(base, 0.0) == true && exponent < 0)
{
debug <<"异常, 指数为负数的情况下,底数不能为0" <<endl;
return 0.0;
}

double res = 1.0;
if(exponent > 0.0)
{
res = PowerNormal(base, exponent);
}
else
{
res = PowerNormal(base, -exponent);
res = 1 / res;
}

return res;
}

private :
double PowerNormal(double base, int exponent)
{

double res = 1;
for(int i = 0; i < exponent; i++)
{
res *= base;
}

return res;

}
double Equal(double left, double right)
{
if(fabs(left - right) <  0.0000001)
{
return true;
}
else
{
return false;
}
}
};

int __tmain( )
{
Solution solu;

cout <<solu.Power(2, 0) <<endl;
cout <<solu.Power(2, -3) <<endl;
return 0;
}


位运算(全面而且高效的算法)

那么还有没有更加快速的办法呢?

别急,我们慢慢来分析

写出指数的二进制表达,例如13表达为二进制1101。

举例:10^1101 = 10^0001*10^0100*10^1000。

通过&1和>>1来逐位读取1101,为1时将该位代表的乘数累乘到最终结果。

简单明了,看来结果根指数中1的个数和位置有关系,那么就简单了,还记得剑指Offer–010-二进制中1的个数

double PowerNormal(double base, int exponent)
{
if(exponent == 0)
{
return 1;
}
else if(exponent == 1)
{
return base;
}

int res = 1, temp = base;
while(exponent != 0)
{
if((exponent & 1) == 1) //  当前指数为不为0
{
res *= temp;        //  就计算一个乘积
}
//  移位后, curr需要翻倍, 这样到下个
temp *= temp;           // 翻倍
exponent >>= 1;         // 右移一位
}
return res;
}


当然也可以用递归的写法

double PowerNormal(double base, int exponent)
{
if(exponent == 0)
{
return 1;
}
else if(exponent == 1)
{
return base;
}
double res = PowerNormal(base, exponent >> 1);
res *= res;
if((exponent & 1) == 1)
{
res *= base;
}

return res;
}


“`
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息