`
iwebcode
  • 浏览: 2013625 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

数值的整数次方

 
阅读更多

题目:实现函数doublePower(double base, int exponent),求baseexponent次方。不需要考虑溢出。

分析:这是一道看起来很简单的问题。可能有不少的人在看到题目后30秒写出如下的代码:

double Power(double base, int exponent)

{

double result = 1.0;

for(int i = 1; i <= exponent;++i)

result *= base;

return result;

}

上述代码至少有一个问题:由于输入的exponent是个int型的数值,因此可能为正数,也可能是负数。上述代码只考虑了exponent为正数的情况。

接下来,我们把代码改成:

boolg_InvalidInput = false;

double Power(double base, int exponent)

{

g_InvalidInput = false;

if(IsZero(base)&& exponent < 0)

{

g_InvalidInput = true;

return 0.0;

}

unsigned int unsignedExponent = static_cast<unsigned int>(exponent);

if(exponent< 0)

unsignedExponent = static_cast<unsigned int>(-exponent);

double result =PowerWithUnsignedExponent(base, unsignedExponent);

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;

}

上述代码较之前的代码有了明显的改进,主要体现在:首先它考虑了exponent为负数的情况。其次它还特殊处理了当底数base0而指数exponent为负数的情况。如果没有特殊处理,就有可能出现除数为0的情况。这里是用一个全局变量来表示无效输入。关于不同方法来表示输入无效的讨论,详见本系列第17

最后需要指出的是:由于0^0次方在数学上是没有意义的,因此无论是输入0还是1都是可以接受的,但需要在文档中说明清楚。

这次的代码在逻辑上看起来已经是很严密了,那是不是意味了就没有进一步改进的空间了呢?接下来我们来讨论一下它的性能:

如果我们输入的指数exponent32,按照前面的算法,我们在函数PowerWithUnsignedExponent中的循环中至少需要做乘法31次。但我们可以换一种思路考虑:我们要求出一个数字的32次方,如果我们已经知道了它的16次方,那么只要在16次方的基础上再平方一次就可以了。而16次方是8次方的平方。这样以此类推,我们求32次方只需要做5次乘法:求平方,在平方的基础上求4次方,在4次方的基础上平方求8次方,在8次方的基础上求16次方,最后在16次方的基础上求32次方。

32刚好是2的整数次方。如果不巧输入的指数exponent不是2的整数次方,我们又该怎么办呢?我们换个数字6来分析,6就不是2的整数次方。但我们注意到6是等于2+4,因此我们可以把一个数的6次方表示为该数的平方乘以它的4次方。于是,求一个数的6次方需要3次乘法:第一次求平方,第二次在平方的基础上求4次方,最后一次把平方的结果和4次方的结果相乘。

现在把上面的思路总结一下:把指数分解了一个或若干个2的整数次方。我们可以用连续平方的方法得到以2的整数次方为指数的值,接下来再把每个前面得到的值相乘就得到了最后的结果。

到目前为止,我们还剩下一个问题:如何将指数分解为一个或若干个2的整数次方。我们把指数表示为二进制数再来分析。比如6的二进制表示为110,在它的第2位和第3位为1,因此6=2^(2-1)+2^(3-1) 。也就是说只要它的第n位为1,我们就加上2n-1次方。

最后,我们根据上面的思路,重写函数PowerWithUnsignedExponent

double PowerWithUnsignedExponent(double base, unsigned int exponent)

{

std::bitset<32> bits(exponent);

if(bits.none())

return 1.0;

int numberOf1 =bits.count();

double multiplication[32];

for(int i= 0; i < 32; ++i)

{

multiplication[i] = 1.0;

}

//if the i-th bit in exponent is 1,

//the i-th number in array multiplication is base ^ (2 ^ n)

intcount = 0;

double power = 1.0;

for(int i= 0; i < 32 && count < numberOf1; ++i)

{

if(i== 0)

power= base;

else

power= power * power;

if(bits.at(i))

{

multiplication[i]= power;

++count;

}

}

power = 1.0;

for(int i= 0; i < 32; ++i)

{

if(bits.at(i))

power*= multiplication[i];

}

return power;

}

在上述代码中,我们用C++的标准函数库中bitset把整数表示为它的二进制,增大代码的可读性。如果exponent的第i位为1,那么在数组multiplication的第i个数字中保存以base为底数,以2i次方为指数的值。最后,我们再把所以位为1在数组中的对应的值相乘得到最后的结果。

上面的代码需要我们根据base的二进制表达的每一位来确定是不是需要做乘法。对二进制的操作很多人都不是很熟悉,因此编码可能觉得有些难度。我们可以换一种思路考虑:我们要求出一个数字的32次方,如果我们已经知道了它的16次方,那么只要在16次方的基础上再平方一次就可以了。而16次方是8次方的平方。这样以此类推,我们求32次方只需要做5次乘法:先求平方,在平方的基础上求4次方,在4次方的基础上平方求8次方,在8次方的基础上求16次方,最后在16次方的基础上求32次方。

也就是说,我们可以用如下公式求an次方:

这个公式很容易就能用递归来实现。新的PowerWithUnsignedExponent代码如下:

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;

}

分享到:
评论

相关推荐

    数值的整数次方.md

    数值的整数次方.md

    java基础面试题数值的整数次方

    java基础面试题数值的整数次方本资源系百度网盘分享地址

    js代码-200615-数值的整数次方

    js代码-200615-数值的整数次方

    数值的整数次方1

    示例 1:输入: 2.00000, 10 输出: 1024.00000示例 2:输入: 2.10000, 3 输出: 9.26100// 当 x 是 0 而 n

    bbkgl#notes#数值的整数次方1

    下面说下思路:如果a&gt;=0:边界条件:a^0 = 1, a^1 = a;如果a边界条件:a^0 = 1, a^-1 =1 / a;代码如下:double

    剑指Offer(Python多种思路实现):数值的整数次方

    剑指Offer(Python多种思路实现):数值的整数次方 面试16题: 题目:数值的整数次方 题:实现函数double Power(double base, int exponent),求base的exponent次方、不得使用库函数,同时不需要考虑大数问题。 解题...

    yzytmac#Notes#面试题11:数值的整数次方1

    当指数为负数的时候,可以先对指数求绝对值,然后算出次方的结果之后再取倒数,当底数(base)是零且指数是负数的时候,如果不做特殊处理,就会出现对0求倒数从而导致

    trollyxia#CodingInterviews#012-数值的整数次方1

    保证base和exponent不同时为0思路要注意特殊情况:指数为0的情况,不管底数是多少都应该是1指数为负数的情况,求出的应该是其倒数幂的倒数指数为负数的情况

    wangrui996#leedcode#0016.数值的整数次方1

    2.经过上面的转换问题就变成了两个子问题,我们用循环解决: 1.如果x == 0 && n 3.初始化结果res = 1

    Python《剑指offer》算法实现-数值的整数次方

    # Python实现《剑指offer》 部分代码自己添加了一些测试用例, 或者自己添加了一些功能 1. 初级程序员注重算法和数据结构 2. 事先做好准备,对工作有热情 3. 面试过程放松。不要急于写代码,了解清楚所要解决的问题,...

    hairrrrr#1200_Problems#40_数值的整数次方1

    示例 1:输入: 2.00000, 10输出: 1024.00000示例 2:输入: 2.10000, 3输出: 9.26100示例 3:输入: 2.00000

    floatLig#CSLearning#面试题16.数值的整数次方1

    示例 1:输入: 2.00000, 10输出: 1024.00000示例 2:输入: 2.10000, 3输出: 9.26100示例 3:输入: 2.00000

    面试题16:数值的整数次方

    一、虽然计算能够显示正确结果,但是对无效输入(即基数为0且指数为负)不能够很好的标明出来,即可能会忽略isInvaildInput的一个表达 #include class c_Pow { bool isInvalidInput; double result;...

    剑指offer 题16——数值的整数次方

    数值的整数次方 题目: 实现函数double Power(double base,int exponent), 求base得exponent次方。不得使用库函数,同时不需要考虑大数问题 因为不需要考虑大数问题,所以看起来似乎很简单,只需要累加就好 double ...

    16:数值的整数次方(剑指offer第2版Python)

    给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。 2、代码详解 先说结论: 特例:底数为0且指数为负,抛异常“0不能求倒数” equal_zero时,因为计算机内表示小数有误差,要写成abs...

    大整数乘法分治算法(10的256次方乘以10的256次方)

    大整数在密码学、生物信息、基因工程等多个 领域都有重要的应用价值。大整数无法在程序设 计语言能直接表示的整数范围内...计算结果中所有数位上的精确数值,并提高计算 的效率,必须选择合适的数据结构和有效的算法。

    为面试做准备的python经典编程题之1

    数组中重复的数字.py 二维数组中的查找.py 替换空格.py 从尾到头打印链表.py 重建二叉树.py 二叉树的下一个节点.py 用两个栈实现队列.py ...数值的整数次方.py 打印从1到最大的n位数.py 删除链表的节点.py

    目前最火最热门的python经典编程题之1

    3.数组中重复的数字 Array 常考 4.二维数组中的查找 Array 常考 5.替换空格 String 6.从尾到头打印链表 Linked List ...16.数值的整数次方 Math, 关注 17.打印从1到最大的n位数 18.O(1)时间删除链表节点 Linked List

    ACCESS基本函数大全

    access基本函数介绍。 类型 函数名 函数格式 说明 算 术 函 数 绝对值 Abs(&lt;数值... 自然指数 Exp(&lt;数值表达式&gt;) 计算e的N次方,返回一个双精度 自然对数 Log(&lt;数值表达式&gt;) 计算以e为底的数值表达式的值的对数

Global site tag (gtag.js) - Google Analytics