power(乘幂)函数剖析

近来学习STL,看到power函数的实现感觉挺有趣,记录一下。

1. 一般情况下,我自己要实现乘幂函数会这样实现:

int power(int x,size_t n)
{
    int result = 1;
    while (n--)
        result *= x;
    return result;
}

这样即使实现,这里的时间复杂度和n有关,时间复杂度为0(n)。

2. 看了stl源码实现是这样:

// Returns __x ** __n, where __n >= 0.  _Note that "multiplication"
// is required to be associative, but not necessarily commutative.
//意思是multiplication要满足结合律,但不需要满足交换律

template <class _Tp, class _Integer, class _MonoidOperation>
_Tp __power(_Tp __x, _Integer __n, _MonoidOperation __opr)  //这里第三个参数是一个二元操作函数
{
    if (__n == 0)
        return identity_element(__opr);           //返回1
    else
    {
        while ((__n & 1) == 0)                   //如果n为偶数
        {
            __n >>= 1;
            __x = __opr(__x, __x);
        }

        _Tp __result = __x;
        __n >>= 1;
        while (__n != 0)
        {
            __x = __opr(__x, __x);
            if ((__n & 1) != 0)                    //如果n为奇数
                __result = __opr(__result, __x);
            __n >>= 1;
        }
        return __result;
    }
}

template <class _Tp, class _Integer>
inline _Tp __power(_Tp __x, _Integer __n)
{
    return __power(__x, __n, multiplies<_Tp>());
}

// Alias for the internal name __power.  Note that power is an extension,
// not part of the C++ standard.

template <class _Tp, class _Integer, class _MonoidOperation>
inline _Tp power(_Tp __x, _Integer __n, _MonoidOperation __opr)   //也可以自定义,传进去一个函数
{
    return __power(__x, __n, __opr);
}

template <class _Tp, class _Integer>
inline _Tp power(_Tp __x, _Integer __n)   //默认情况下是乘幂
{
    return __power(__x, __n);
}

这里:当n为偶数时,X^n=(X^2)^(2/n),此时看2/n是否还是偶数,如果是则继续,否则,转向n是奇数的情况;

当n为奇数时,X^n=X*X^(n-1);

例如计算5^6=(5^2)^3,也就是计算25^3。

这种情况和第三种情况类似,只是当n开始为偶数时,比第三种方法的效率更高,n为奇数时,和第三种方法时间复杂度一样。

3. 看了还有一种实现,和stl源码差不多,只是表示更简洁,和第二种情况相比效率会差点:

int power(int x, size_t n)
{
    if(n == 0)
        return 1;
    int result = 1;
    while(n)
    {
        if(n & 1)                    //n为奇数时
            result *= x;
        n >>= 1;
        x *= x;
    }
}

如计算5^6是6化为二进制为0110,所以这里5^6=5^2*5^4,这里时间复杂度为0((log2n)+1)

时间: 2025-01-02 16:05:58

power(乘幂)函数剖析的相关文章

自执行匿名函数剖析

引入 在很多js代码中我们常常会看见这样一种写法: (function( window, undefined ) { // code })(window); 这种写法我们称之为自执行匿名函数(self-executing anonymous function). 正如它的名字一样,它是自己执行自己的,前一个括号是一个匿名函数,后一个括号代表立即执行. 函数和函数表达式的区别 语法 function keqing(){ //函数 alert('Hi~'); } var keqing = funct

STM32的GPIO使用的函数剖析

转载http://blog.csdn.net/wuwuhuizheyisheng/article/details/8239599 STM32的GPIO总结 作者:JCY 该文是自己学习了一段STM32后所写,是对STM32使用固件库编程最简单的一段程序,是对固件库函数的一部分进行解析.如有错误之处请指正,不胜感激. 一. GPIO_Init函数解析 1 1.参数GPIO_TypeDef 1 2.参数GPIO_InitStruct 2 3.函数代码详解 4 4.备注 6 一.GPIO_Init函数

CodeIgniter框架——函数剖析+小知识点

连接数据库: 格式: mysql -h主机地址 -u用户名-p用户密码 数据库的提示符:mysql> 退出数据库: exit(回车) 知识点积累: 1.date_default_timezone_set — 设定用于一个脚本中所有日期时间函数的默认时区 格   式:bool date_default_timezone_set ( string $timezone_identifier ) 参   数:timezone_identifier,时区标识符,例如 UTC 或 Europe/Lisbon

Python开发【第四章】:Python函数剖析

一.Python装饰器 定义:本质是函数(装饰其他函数),为其他函数添加附件功能的. 遵循原则:①不能修改被装饰函数的源代码 ②不能修改被装饰函数的调用方式 组成:装饰器由高阶函数+内嵌函数+闭包组成 1.函数的调用顺序 #!/usr/bin/env python # -*- coding:utf-8 -*- #-Author-Lian #函数错误的调用方式 def func(): #定义函数func() print("in the func") foo() #调用函数foo() fu

FFmpeg av_probe_input_buffer函数剖析以及优化

函数调用关系av_probe_input_buffer调用av_probe_input_buffer2进行整一个码流格式的分析过程.其中调用avio_read进行码流数据的读取,将缓存数据保存在AVProbeData定义的buf里面,然后调用av_probe_input_format2(AVProbeData *pd, int is_opened, int *score_max)函数去猜测码流格式,其中包裹最终的调用函数av_probe_input_format3. 优化方向如果知道AVInpu

FFmpeg init_input函数剖析

函数调用逻辑avformat_open_input       init_input            av_probe_input_buffer2 函数原型 static int init_input(AVFormatContext *s, const char *filename, AVDictionary **options) 函数说明主要是调用av_probe_input_buffer2函数探测码流格式.AVFormatContext结构体flags变量,在经过avformat_al

FFmpeg mov_read_ftyp函数剖析

函数说明 读取文件格式,最小版本以及兼容格式,然后存储到metadata,metadata作为AVFormatContext成员变量,可以通过t = av_dict_get(pAVFormatContext->metadata, "major_brand", NULL, AV_DICT_IGNORE_SUFFIX);查看文件格式 /* read major brand, minor version and compatible brands and store them as m

FFmpeg avio_alloc_context函数剖析

函数原型AVIOContext *avio_alloc_context(                  unsigned char *buffer,                  int buffer_size,                  int write_flag,                  void *opaque,                  int (*read_packet)(void *opaque, uint8_t *buf, int buf_siz

FFmpeg ff_h264_parse_sprop_parameter_sets函数剖析

SDP中SPS内容        sprop-parameter-sets=Z0IAKpY1QPAET8s3AQEBQAABwgAAV+QB,aM48gA== 该函数主要是读取Z0IAKpY1QPAET8s3AQEBQAABwgAAV+QB的内容到data_ptr,一共32个字节还没有读取SPS的每一个字段,然后赋值给SPS相应的字段int ff_h264_parse_sprop_parameter_sets(AVFormatContext *s,