`
frank-liu
  • 浏览: 1668623 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

快速指数运算方法

 
阅读更多

问题描述

    我们在一些常用的运算里免不了要计算某些指数函数。比如说给定两个正整数a, b,要求a**b,即a的b次方。这个问题看起来很简单,最直接的办法就是我连续乘以a,b次,得到的就是这个结果。这种方法的时间复杂度也比较低,相当于O(N)。实际上,我们还有更好的办法,使得它的时间复杂度达到O(logN)。

 

分析

    实际上这个问题本身并不是很复杂,从一开始看的时候似乎也能找到一点类似的苗头。比如说我们要求2 ** 7。我们知道,它可以拆分成2**4 * 2 ** 3。而对于2的4次方可以拆分成2**2 再做一次平方。对于一个理想的数字,比如说这个指数本身就是2的多少次方的,像4, 我们只要求出2**2,然后再在它的基础上求它自己的平方,这不就得到2**4了吗?而对于前面2的7次方这个数字,我们将它拆成了2**4乘以2**3。既然2的4次方可以这样来求,对于这些奇数来说呢?实际上我们可以进一步拆分的。2**3可以拆成2**2再乘以2。这样,它们都可以被拆分成一系列的数字给拼起来。

    这个过程似乎带来了一点思路。我们针对前面这个问题再深入的看一下,假设我们要求的这个数字的指数是7, 对它的拆分是将它拆成4和3。因为4是最接近它的2的指数,它可以通过两次求平方运算得到。而3呢,则需要再进一步按照这种方式来拆分。相当于找最接近它的那个2的指数。那么怎么找这个最接近它本身的2的指数呢?我们看7它的二进制表示形式:

    这是一个用4个位来表示的二进制数字形式。其实,它最接近的那个2的指数不就是为1的最高位么?那么我们最终要凑这个数字无非就是将各个为1的位对应的数字加起来。既然我们的目的是将这些数字加起来,那么完全就没有必要考虑从左往右的拆分了。我们完全可以这样来求,看一个数字的某个位是否为1,比如我们从最低位开始。如果是1, 我们就加上一个2**0,也就是1, 而再往后一位对应的第1位的位置, 如果这一个位置也是1的话,则加一个2**1的值。后面依次类推,对应的分别是2**2, 2**3等等。我们这里相当于得出来一个根据二进制数字来凑这个整数的过程。类似的伪代码如下:

 

while(b != 0) {  // 如果这个要凑的数字不为0
    r = b % 2;    // 取出最低位
    b /= 2;
    k = 0;
    if(r == 1)
        sum += (2 ** k)  // 如果当前的位为1, 则表示当前位有数字,加上对应的2的k次方。
    k++;
}

    这里的过程是根据2进制数来求对应整数的。而我们这里具体的问题是要求对应的指数。这里也比较简单,我们对应的更加高的一个位相当于原来的数字对它本身做了个平方。而如果对应的这个位为1, 我们就将它乘以原来的一个数字,相当于前面的相加变相乘。所以套用这个框架,我们就可以很容易得到如下的代码:

 

public static long calculate(int a, int b) {
        if(a <= 0 || b <= 0)
            throw new IllegalArgumentException();
        int r;
        long x = a;
        long y = 1;
        while(b != 0) {
            r = b % 2;
            b = b / 2;
            if(r == 1)
                y *= x;
            x = x * x;
        }
        return y;
    }
     这里结合了两个部分,首先要将这个数字拆分成对应的2进制的形式。不过不需要完整的拆开,每次用b % 2得到的就是当前最低位的值。而将b / 2则相当于b的二进制数字向右移动一位,将第二位的数字变成最低位。这样每移一次我们将对应的底数求平方,就对应到这个位的值。

    从时间复杂度的角度来看,因为我们在循环里每次对这个指数向右移动1位。这个数字对应的是logN个二进制位。所以我们总共遍历的次数为logN。也就是时间复杂度为O(logN)。

 

总结

    求指数函数的快速方法无非是用到了几个典型的数学特性。我们知道,对一个数的指数求平方的话,相当于对指数乘以2。所以问题的根源就归结到我们要怎么样来凑出这个给定的指数值。而如果我们对于数字的2进制表示形式比较清楚的话,会发现它们可以归结到一个将数字转化成二进制的样式的问题。

 

参考材料

Mathematics for computer science

  • 大小: 2.8 KB
分享到:
评论

相关推荐

    基于FPGA的实时金融指数行情并行计算方法.pdf

    基于FPGA的实时金融指数行情并行计算方法,涉及一种实时金融指数行情的计算分析方法,尤其对高频的金融期货交易信息进行并行行情分析。将期货套利快速分析、合约推导和行情更新等功能移植到FPGA硬件平台上并行加速...

    2024快速幂算法 超详细教程

    快速幂算法是一种高效的计算幂运算的方法,适用于计算大数的幂运算、计算机图形学中的阴影效果、密码学中的离散对数和指数运算等。通过本文,您将学习快速幂算法的原理、实现步骤、应用场景、优化方法、变体、实践...

    采用阈值的快速边缘检测算法.

    针对原有模糊边缘检测算法计算复杂、适应性差的缺点...该方法避开了原算法中复杂的指数运算,运算量减少了40%左 右;渡越点的自适应性提高了算法的适应性。仿真表明,该算法检测的边缘细、连贯,并且算法 抗噪能力强。

    快速幂知识点以及示例代码.zip

    快速幂算法是一种非常高效的计算幂的方法,特别适用于处理大指数的情况。在传统的幂运算中,我们通常使用连乘的方式来计算 base 的 n 次幂,即 base^n,这种方法的时间复杂度是 O(n),当 n 很大时,计算效率会变得...

    北大青鸟 Java 教材 第7章描述详细,有示例及图解.

    Math 类提供了数学运算方法,包括算术运算、指数运算、对数运算和三角函数运算等。Math 类的常用方法包括: * abs():获取一个数的绝对值。 * max():获取两个数中的最大值。 * min():获取两个数中的最小值。 本...

    快速幂详解和代码实现python

    快速幂是一种高效的算法,主要用于计算形如a^n的幂运算结果,其中a是底数,n是指数。在传统的直接计算方法中,需要进行n次乘法操作,但快速幂算法利用了指数的二进制表示来优化这一过程,将时间复杂度从O(n)降低到O...

    高振荡函数的数值积分Levin方法【MATLAB代码】

    这里使用Levin提出的一种专门应对一类exp指数与三角函数复合而成的高振荡被积函数的数值积分方法,能非常精确地求解出积分结果,降低运算时间。我们这里采用了切比雪夫多项式(而不是泰勒多项式)来提高精度。

    数字信号处理c语言程序集

    1.3指数分布的随机数 1.4拉普拉斯(Laplace)分布的随机数 1.5瑞利(Rayleigh)分布的随机数 1.6对数正态分布的随机数 第一篇 常用数字信号的产生 1.7柯西(Cauchy)分布的随机数 1.8韦伯(Weibull)分布的...

    成年树光模拟的快速计算

    由于该模型计算中存在着大量限制计算效率的几何求交运算,此处根据光照指数与植物暴露面积所具有相同的共同特征,提出采用采用覆盖面积的计算方法来近似拟合GLI的值,并在并行计算架构CUDA上实现了该算法。...

    论文研究-一种快速山峰聚类算法.pdf

    山峰聚类既可以对数据集进行近似聚类,又可以为其他聚类方法提供聚类所需的初始聚类中心。减法聚类是山峰聚类的改进,它避免了山峰聚类中出现的计算量随样本维数增加呈指数增长的情况。但减法聚类对处理大样本集也...

    fast-exponentiation-algs:Domashka在Mehmat SFedU修读的第一年硕士课程

    快速指数藻类 Mehmat SFedU(2013)的1个治安法官课程。 组中的快速求幂方法。 老师:Mayevsky Alexey Eduardovich 常用的取幂方法 从左到右无符号: Veremeenko Artyom 从右到左无符号: Pozdnyakov Alexey 左至...

    二进制输入压缩感测的快速解码和硬件设计

    BiCS与使用逻辑或(XOR)运算生成二进制符号的常规通道代码不同,BiCS通过加权和运算生成多级符号。 尽管BiCS可以通过消息传递进行解码,但它需要在每次迭代中计算概率函数的卷积。 高解码复杂度阻止了该技术被应用...

    常用算法程序集(C语言描述)(第三版)+完整源代码

    第2章 复数运算 2.1 复数乘法 2.2 负数除法 2.3 复数乘幂 2.4 复数的n次方根 2.5 复数指数 2.6 复数对数 2.7 复数正弦 2.8 复数余弦 第3章 随机数的产生 3.1 产生0到1之间均匀分布的一个随机数 3.2 产生0到1之间均匀...

    Jep3.5 数学公式计算 jar包及中文操作手册文档

    24 计算方法 25 快速重复计算 26 Decimal 运算 27 隐式乘法 28 处理多个表达式 29 使用 RealEvaluator 快速计算 三、变量 31 基础 32 未声明和未定义的变量 33 赋值 34 获取变量列表 35 变量观察者 四、数据类型 ...

    实数与文本转化子程序

    我曾经使用过一种算法,即用多次开平方的方式来实现指数运算,但效率只有 pow(a, b) 的六分之一。最后实在无奈,我只要还是使用 pow(a, b) 来算指数。我甚至反汇编 pow(a, b),但没看懂算法,而且也没见代码中使用 ...

    数据结构与算法分析Java语言描述(第二版)

    目录译者序前言第1章 引论1.1 本书讨论的内容1.2 数学知识复习1.2.1 指数1.2.2 对数1.2.3 级数1.2.4 模运算1.2.5 证明的方法1.3 递归简论1.4 实现泛型特性构件pre-Java51.4.1 使用Object表示泛型1.4.2 基本...

Global site tag (gtag.js) - Google Analytics