您的位置:首页 > Web前端

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

2018-01-17 21:15 423 查看

剑指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/2∗an/2,a(n−1)/2∗a(n−1)/2∗a,n为偶数n为奇数

这个公式很容易用递归来实现。隐藏的终止条件是 指数为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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: