以下是使用代码计算 2^8 所采取的步骤:
\n\npower(2,8)=\n2*power(2,7)=\n2*2*power(2,6)=\n2*2*2*power(2,5)=\n2*2*2*2*power(2,4)=\n2*2*2*2*2*power(2,3)=\n2*2*2*2*2*2*power(2,2)=\n2*2*2*2*2*2*2*power(2,1)=\nRun Code Online (Sandbox Code Playgroud)\n\n以下是通过分治法计算 2^8 所采取的步骤:
\n\npower(2,8)=\npower(2,4)**2=\npower(2,2)**2**2=\npower(2,1)**2**2**2=\nRun Code Online (Sandbox Code Playgroud)\n\n正如您所看到的,您的方法需要 O(n) 步骤,而分而治之需要 O(lg(n)) 步骤,这要快得多。
\n\n如果您关心速度,那么使用递归来解决此类问题从来都不是一个好主意,因为正如您所看到的,迭代方法(函数式语言中的尾递归)通常要快得多,在本示例中,它的速度是基准测试中看到的速度的两倍,至于分而治之的方法,你应该始终使用它,除非你使用的幂小于~22。
\n\n以下是一些基准:
\n\n代码:
\n\ndef r_power(base, exponent): # recursive credits to OP\n if exponent == 1:\n return base\n return base * r_power(base, exponent - 1)\n\n\ndef lindc_power(x, y): # linear divide and conquer, credits to Smitha Dinesh Semwal\n if y == 0:\n return 1\n elif int(y % 2) == 0:\n return lindc_power(x, int(y / 2)) * lindc_power(x, int(y / 2))\n else:\n return x * lindc_power(x, int(y / 2)) * lindc_power(x, int(y / 2))\n\n\ndef lgdc_power(x, y): # logarithmic divide and conquer\n if y == 0:\n return 1\n elif int(y % 2) == 0:\n return lgdc_power(x, int(y / 2)) ** 2\n else:\n return x * lgdc_power(x, int(y / 2)) ** 2\n\n\ndef i_power(base, exponent): # iterative, credits to Yugandhar Chaudhari\n acc = 1\n while True:\n if exponent == 0:\n return acc\n base, exponent, acc = base, exponent - 1, acc * base\nRun Code Online (Sandbox Code Playgroud)\n\n结果:
\n\n|---------------------------------------------------------------------|\n| base | power | recursive | iterative | linear dc | logarithmic dc |\n|---------------------------------------------------------------------|\n| 2 | 10 | 1.27 \xc2\xb5s | 746 ns | 8.99 \xc2\xb5s | 2.33 \xc2\xb5s |\n| 2 | 22 | 2.96 \xc2\xb5s | 1.58 \xc2\xb5s | 18.6 \xc2\xb5s | 2.95 \xc2\xb5s |\n| 2 | 100 | 15.1 \xc2\xb5s | 8.31 \xc2\xb5s | 75.3 \xc2\xb5s | 4.14 \xc2\xb5s |\n| 2 | 500 | 96.7 \xc2\xb5s | 48.9 \xc2\xb5s | 312 \xc2\xb5s | 5.69 \xc2\xb5s |\n| 2 | 1000 | 424 \xc2\xb5s | 178 \xc2\xb5s | 1.3 ms | 6.58 \xc2\xb5s |\n| 2 | 1500 | 201 \xc2\xb5s | 108 \xc2\xb5s | 620 \xc2\xb5s | 7.89 \xc2\xb5s |\n| 2 | 2000 | 435 \xc2\xb5s | 242 \xc2\xb5s | 1.23 ms | 8.15 \xc2\xb5s |\n| 2 | 3000 | error | 409 \xc2\xb5s | 2.49 ms | 10.3 \xc2\xb5s |\n| 2 | 6000 | error | 1.13 ms | 5.01 ms | 17.6 \xc2\xb5s |\n| 2 | 10000 | error | 2.64 ms | 9.84 ms | 25.2 \xc2\xb5s |\n| 2 | 20000 | error | 8.74 ms | 19.9 ms | 45.7 \xc2\xb5s |\n| 2 | 100000 | error | 161 ms | 82.4 ms | 249 \xc2\xb5s |\n| 2 | 200000 | error | 626 ms | 159 ms | 532 \xc2\xb5s |\n| 2 | 1000000 | error | 15 s | 651 ms | 3.23 ms |\n|---------------------------------------------------------------------|\n\nRun Code Online (Sandbox Code Playgroud)\n\n我的最大递归深度是 3000。
\n