• python pow函数底层实现原理


    一、最朴素的方法和pow比较

    python中求两个a的b次方,常见的方法有:pow(a,b),a**b。那么这两个是否有区别,而且他们底层是怎么实现的呢?
    最容易想到的方法就是:循环b次,每次都乘以a。但是究竟底层是不是这样实现的呢?
    下面先从时间上来判断他们之间的关系。

    首先来看看,pow和**有没有区别:
    import time
    
    start = time.time()
    print(2 ** 1000000)
    end0 = time.time()
    print('**:', end0 - start)
    print(pow(2, 1000000))
    end1 = time.time()
    print('pow:', end1 - end0)
    

    上面的结果输出如下:

    2的100万次方,两者所用时间是基本一样的,所以他们应该本质上应该使用了相同的算法

    下面再来看看用for循环模拟的结果

    import time
    
    start = time.time()
    print(2 ** 1000000)
    end0 = time.time()
    print('**:', end0 - start)
    
    print(pow(2, 1000000))
    end1 = time.time()
    print('pow:', end1 - end0)
    
    r = 1
    for i in range(1000000):
        r *= 2
    end2 = time.time()
    print('for:', end2 - end1)
    

    上面的输入结果如下:

    非常恐怖的对比,pow和**都只用了1.5秒,而for循环用来20秒!,所以可以肯定的是,pow底层绝对不是用循环去求解的

    pow底层实现

    我们分析一下为什么直接循环相乘效率会这么低,我们其实不难发现里面有大量的重复运算,比如我们算出22后面,还不断重复着计算22的结果,所以我们只要保存这些中间必要的计算结果后你不断重复利用就可以大大减少运算量。举个例子,比如我们现在在计算2的9次方,我们可以这样子计算,先算出22然后不断利用这个结果:
    (2
    2)(22)(22)(22)2 即44442 只要计算5次
    同理可以再利用上面的4
    4 可以的16162
    具体实现程序如下:

    def fun(a, b):
        r = 1
        while b > 1:
            if b & 1 == 1:  #与运算一般可以用于取某位数,这里就是取最后一位。
                r *= a
            a *= a
            b = b >> 1 #这里等价于b//=2 
        return r * a
    

    接下我们来看看,究竟pow函数底层是不是这样实现的

    import time
    
    start = time.time()
    print(2 ** 1000000)
    end0 = time.time()
    print('**:', end0 - start)
    print(pow(2, 1000000))
    end1 = time.time()
    print('pow:', end1 - end0)
    r = 1
    for i in range(1000000):
        r *= 2
    end2 = time.time()
    print('for:', end2 - end1)
    print(fun(2, 1000000))
    print('fun:', time.time() - end2)
    


    从上面可以看出来,pow函数运行的时间基本和自定义的函数一致,甚至自定制的还更快!
    解析完毕!

  • 相关阅读:
    CNI 这么多,怎么选?| 容器网络系列第 1 期
    FabEdge 成为 CNCF 沙箱级项目
    向 Analysis Services 实例授予服务器管理员权限
    Connecting to Integration Services Access is Denied in SQL Server 2016 or 2017
    How To Convert A CER Certificate To PFX Without The Private Key
    Linux Shell脚本经典案例
    MDK5 HC32F460编译生成BIN文件配置
    MDK5 魔术棒中target中的IROM1与IRAM1
    Mongodb副本集切换主从节点调整优先级
    mongodb 创建用户,设置密码
  • 原文地址:https://www.cnblogs.com/linshuhui/p/9885696.html
Copyright © 2020-2023  润新知