python - 使用递归寻找力量
问题描述
在 Python 3 中
def power(base,exponent):
if exponent == 1:
return base
return base * power(base, exponent - 1)
我没有考虑过极端情况(指数<= 0)
为什么我们不使用上面编写的代码来代替使用分而治之技术计算的代码,这段代码看起来更简单易懂?这段代码的效率会降低吗?
解决方案
这些是使用您的代码计算 2^8 所采取的步骤:
power(2,8)=
2*power(2,7)=
2*2*power(2,6)=
2*2*2*power(2,5)=
2*2*2*2*power(2,4)=
2*2*2*2*2*power(2,3)=
2*2*2*2*2*2*power(2,2)=
2*2*2*2*2*2*2*power(2,1)=
这些是用分而治之计算 2^8 所采取的步骤:
power(2,8)=
power(2,4)**2=
power(2,2)**2**2=
power(2,1)**2**2**2=
如您所见,您的方法需要 O(n) 步,而分而治之需要 O(lg(n)) 步,这要快得多。
如果您关心速度,那么对此类问题使用递归绝不是一个好主意,因为正如您所见,迭代方法(函数式语言中的尾递归)通常要快得多,在此示例中,它的速度是您在基准测试中看到的两倍,至于分而治之的方法,你应该总是使用它,除非你使用的权力小于~22。
以下是一些基准:
代码:
def r_power(base, exponent): # recursive credits to OP
if exponent == 1:
return base
return base * r_power(base, exponent - 1)
def lindc_power(x, y): # linear divide and conquer, credits to Smitha Dinesh Semwal
if y == 0:
return 1
elif int(y % 2) == 0:
return lindc_power(x, int(y / 2)) * lindc_power(x, int(y / 2))
else:
return x * lindc_power(x, int(y / 2)) * lindc_power(x, int(y / 2))
def lgdc_power(x, y): # logarithmic divide and conquer
if y == 0:
return 1
elif int(y % 2) == 0:
return lgdc_power(x, int(y / 2)) ** 2
else:
return x * lgdc_power(x, int(y / 2)) ** 2
def i_power(base, exponent): # iterative, credits to Yugandhar Chaudhari
acc = 1
while True:
if exponent == 0:
return acc
base, exponent, acc = base, exponent - 1, acc * base
结果:
|---------------------------------------------------------------------|
| base | power | recursive | iterative | linear dc | logarithmic dc |
|---------------------------------------------------------------------|
| 2 | 10 | 1.27 µs | 746 ns | 8.99 µs | 2.33 µs |
| 2 | 22 | 2.96 µs | 1.58 µs | 18.6 µs | 2.95 µs |
| 2 | 100 | 15.1 µs | 8.31 µs | 75.3 µs | 4.14 µs |
| 2 | 500 | 96.7 µs | 48.9 µs | 312 µs | 5.69 µs |
| 2 | 1000 | 424 µs | 178 µs | 1.3 ms | 6.58 µs |
| 2 | 1500 | 201 µs | 108 µs | 620 µs | 7.89 µs |
| 2 | 2000 | 435 µs | 242 µs | 1.23 ms | 8.15 µs |
| 2 | 3000 | error | 409 µs | 2.49 ms | 10.3 µs |
| 2 | 6000 | error | 1.13 ms | 5.01 ms | 17.6 µs |
| 2 | 10000 | error | 2.64 ms | 9.84 ms | 25.2 µs |
| 2 | 20000 | error | 8.74 ms | 19.9 ms | 45.7 µs |
| 2 | 100000 | error | 161 ms | 82.4 ms | 249 µs |
| 2 | 200000 | error | 626 ms | 159 ms | 532 µs |
| 2 | 1000000 | error | 15 s | 651 ms | 3.23 ms |
|---------------------------------------------------------------------|
我的最大递归深度是 3000。
推荐阅读
- matlab - 从 ASCII 文件导入表
- java - 远程服务器上的肥皂调用速度较慢
- android - 上传Playstore免费和付费应用程序国家明智
- python - 将元组中的元素转换为类似字节的对象
- angular - 如何将 ngc 安装为项目特定的 cli 工具?
- logging - ELK Logstash 中的日期解析问题与日志的自定义 Java 时间戳格式
- c - 字符串与字符串文字:直接赋值还是 strcpy/strncpy?
- css - CSS - 选择文本元素
- batch-file - 在 Windows 10 的系统启动中放置 .bat 和 .vbs 脚本
- node.js - 如果 Node 设置为 staging,为什么 Rect .env 会提供 Production?