@@ -1190,8 +1190,7 @@ \subsubsection{尾递归}
1190
1190
1191
1191
作为本节的结尾,我们考虑一个有趣的题目,如何设计一个算法来高效地计算$ b^n$ ?(参考\cite {SICP }中的1.16节。)
1192
1192
1193
- A naive brute-force solution is to repeatedly multiply $ b$ for $ n$ times from 1, which leads to a
1194
- linear $ O(n)$ algorithm.
1193
+ 最直接的方法是从1开始重复乘以$ b$ 共$ n$ 次,这是一个线性时间$ O(n)$ 的算法。
1195
1194
1196
1195
\begin {algorithmic }[1]
1197
1196
\Function {Pow}{$ b, n$ }
@@ -1203,21 +1202,18 @@ \subsubsection{尾递归}
1203
1202
\EndFunction
1204
1203
\end {algorithmic }
1205
1204
1206
- Actually, the solution can be greatly improved. Consider we are trying to calculate $ b^8 $ .
1207
- By the first 2 iterations in above naive algorithm, we got $ x = b^2 $ . At this stage, we
1208
- needn't multiply $ x$ with $ b$ to get $ b^3 $ , we can directly calculate $ x^2 $ , which leads
1209
- to $ b^4 $ . And if we do this again, we get $ (b^4 )^2 = b^8 $ . Thus we only need looping 3 times
1210
- but not 8 times.
1205
+ 我们考虑如何改进它。考虑计算$ b^8 $ 的过程,上述算法经过前两次迭代,可以得到$ x = b^2 $ 的结果。此时,我们无需再次用$ x$ 乘以$ b$ 得到$ b^3 $ ,可以直接再次乘以$ b^2 $ ,从而得到$ b^4 $ 。然后再次乘方,就可以得到$ (b^4 ) = b^8 $ 。这样总共只要循环3次,而不是8次。
1211
1206
1207
+ 若
1212
1208
An algorithm based on this idea to compute $ b^n$ if $ N = 2 ^M$ for some non-negative integer $ m$ can be shown in
1213
1209
the following equation.
1214
1210
1215
1211
\[
1216
1212
pow(b, n) = \left \{
1217
1213
\begin {array }
1218
1214
{r@{\quad :\quad }l}
1219
- b & N = 1 \\
1220
- pow(b, \frac {N }{2})^2 & otherwise
1215
+ b & n = 1 \\
1216
+ pow(b, \frac {n }{2})^2 & otherwise
1221
1217
\end {array }
1222
1218
\right .
1223
1219
\]
@@ -1226,8 +1222,8 @@ \subsubsection{尾递归}
1226
1222
1227
1223
\begin {itemize }
1228
1224
\item For the trivial case, that $ n$ is zero, the result is 1;
1229
- \item If $ n$ is even number, we can halve $ n$ , and compute $ b^{\frac {N }{2}}$ first. Then calculate the square number of this result.
1230
- \item Otherwise, $ n$ is odd. Since $ N -1 $ is even, we can first recursively compute $ b^{N -1}$ , the multiply $ b$ one more time to this result.
1225
+ \item If $ n$ is even number, we can halve $ n$ , and compute $ b^{\frac {n }{2}}$ first. Then calculate the square number of this result.
1226
+ \item Otherwise, $ n$ is odd. Since $ n -1 $ is even, we can first recursively compute $ b^{n -1}$ , the multiply $ b$ one more time to this result.
1231
1227
\end {itemize }
1232
1228
1233
1229
Below equation formalizes this description.
@@ -1236,9 +1232,9 @@ \subsubsection{尾递归}
1236
1232
pow(b, n) = \left \{
1237
1233
\begin {array }
1238
1234
{r@{\quad :\quad }l}
1239
- 1 & N = 0 \\
1240
- pow(b, \frac {N }{2})^2 & 2 | N \\
1241
- b \times pow(b, N -1) & otherwise
1235
+ 1 & n = 0 \\
1236
+ pow(b, \frac {n }{2})^2 & 2 | n \\
1237
+ b \times pow(b, n -1) & otherwise
1242
1238
\end {array }
1243
1239
\right .
1244
1240
\ee
@@ -1250,30 +1246,30 @@ \subsubsection{尾递归}
1250
1246
pow(b, n) = \left \{
1251
1247
\begin {array }
1252
1248
{r@{\quad :\quad }l}
1253
- 1 & N = 0 \\
1254
- pow(b^2, \frac {N }{2}) & 2 | N \\
1255
- b \times pow(b, N -1) & otherwise
1249
+ 1 & n = 0 \\
1250
+ pow(b^2, \frac {n }{2}) & 2 | n \\
1251
+ b \times pow(b, n -1) & otherwise
1256
1252
\end {array }
1257
1253
\right .
1258
1254
\ee
1259
1255
1260
- With this change, it's easy to get a tail-recursive algorithm as the following, so that $ b^N = pow'(b, N , 1 )$ .
1256
+ With this change, it's easy to get a tail-recursive algorithm as the following, so that $ b^n = pow'(b, n , 1 )$ .
1261
1257
1262
1258
\be
1263
- pow'(b, N , A) = \left \{
1259
+ pow'(b, n , A) = \left \{
1264
1260
\begin {array }
1265
1261
{r@{\quad :\quad }l}
1266
- A & N = 0 \\
1267
- pow'(b^2, \frac {N }{2}, A) & 2 | N \\
1268
- pow'(b, N -1, A \times b) & otherwise
1262
+ A & n = 0 \\
1263
+ pow'(b^2, \frac {n }{2}, A) & 2 | n \\
1264
+ pow'(b, n -1, A \times b) & otherwise
1269
1265
\end {array }
1270
1266
\right .
1271
1267
\ee
1272
1268
1273
1269
Compare to the naive brute-force algorithm, we improved the performance to $ O(\lg n)$ .
1274
1270
Actually, this algorithm can be improved even one more step.
1275
1271
1276
- Observe that if we represent $ n$ in binary format $ N = (a_ma_{m-1}...a_1 a_0 )_2 $ , we clear know
1272
+ Observe that if we represent $ n$ in binary format $ n = (a_ma_{m-1}...a_1 a_0 )_2 $ , we clear know
1277
1273
that the computation for $ b^{2^i}$ is necessary if $ a_i = 1 $ . This is quite similar to the
1278
1274
idea of Binomial heap (reader can refer to the chapter of binomial heap in this book). Thus
1279
1275
we can calculate the final result by multiplying all of them for bits with value 1.
@@ -1293,12 +1289,12 @@ \subsubsection{尾递归}
1293
1289
Summarize this idea, we can improve the algorithm as below.
1294
1290
1295
1291
\be
1296
- pow'(b, N , A) = \left \{
1292
+ pow'(b, n , A) = \left \{
1297
1293
\begin {array }
1298
1294
{r@{\quad :\quad }l}
1299
- A & N = 0 \\
1300
- pow'(b^2, \frac {N }{2}, A) & 2 | N \\
1301
- pow'(b^2, \lfloor \frac {N }{2} \rfloor , A \times b) & otherwise
1295
+ A & n = 0 \\
1296
+ pow'(b^2, \frac {n }{2}, A) & 2 | n \\
1297
+ pow'(b^2, \lfloor \frac {n }{2} \rfloor , A \times b) & otherwise
1302
1298
\end {array }
1303
1299
\right .
1304
1300
\ee
@@ -1307,8 +1303,8 @@ \subsubsection{尾递归}
1307
1303
which is the lowest bit) is 0, it means $ n$ is even. It goes on computing the square of the base, without accumulating the
1308
1304
final product (Just like the 3rd step in above example); If the LSB is 1, it means $ n$ is odd. It squares the base and
1309
1305
accumulates it to the product $ A$ ; The edge case is when $ n$ is zero, which means we exhaust all the bits in $ n$ , thus
1310
- the final result is the accumulator $ A$ . At any time, the updated base number $ b'$ , the shifted exponent number $ N '$ ,
1311
- and the accumulator $ A$ satisfy the invariant that $ b^N = b'^{N '}A$ .
1306
+ the final result is the accumulator $ A$ . At any time, the updated base number $ b'$ , the shifted exponent number $ n '$ ,
1307
+ and the accumulator $ A$ satisfy the invariant that $ b^n = b'^{n '}A$ .
1312
1308
1313
1309
This algorithm can be implemented in Haskell like the following.
1314
1310
0 commit comments