From a9a699b4427d40d21c92d62198b8d33ce2b39364 Mon Sep 17 00:00:00 2001 From: LIU Xinyu Date: Wed, 2 Mar 2016 07:53:10 +0800 Subject: [PATCH] [list] uniformed the symboal in pow calculation --- others/appendix/list/list-zh-cn.tex | 54 +++++++++++++---------------- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/others/appendix/list/list-zh-cn.tex b/others/appendix/list/list-zh-cn.tex index 0d3961d5dd..fc00d6c3b6 100644 --- a/others/appendix/list/list-zh-cn.tex +++ b/others/appendix/list/list-zh-cn.tex @@ -1190,8 +1190,7 @@ \subsubsection{尾递归} 作为本节的结尾,我们考虑一个有趣的题目,如何设计一个算法来高效地计算$b^n$?(参考\cite{SICP}中的1.16节。) -A naive brute-force solution is to repeatedly multiply $b$ for $n$ times from 1, which leads to a -linear $O(n)$ algorithm. +最直接的方法是从1开始重复乘以$b$共$n$次,这是一个线性时间$O(n)$的算法。 \begin{algorithmic}[1] \Function{Pow}{$b, n$} @@ -1203,12 +1202,9 @@ \subsubsection{尾递归} \EndFunction \end{algorithmic} -Actually, the solution can be greatly improved. Consider we are trying to calculate $b^8$. -By the first 2 iterations in above naive algorithm, we got $x = b^2$. At this stage, we -needn't multiply $x$ with $b$ to get $b^3$, we can directly calculate $x^2$, which leads -to $b^4$. And if we do this again, we get $(b^4)^2 = b^8$. Thus we only need looping 3 times -but not 8 times. +我们考虑如何改进它。考虑计算$b^8$的过程,上述算法经过前两次迭代,可以得到$x = b^2$的结果。此时,我们无需再次用$x$乘以$b$得到$b^3$,可以直接再次乘以$b^2$,从而得到$b^4$。然后再次乘方,就可以得到$(b^4) = b^8$。这样总共只要循环3次,而不是8次。 +若 An algorithm based on this idea to compute $b^n$ if $N = 2^M$ for some non-negative integer $m$ can be shown in the following equation. @@ -1216,8 +1212,8 @@ \subsubsection{尾递归} pow(b, n) = \left \{ \begin{array} {r@{\quad:\quad}l} - b & N = 1 \\ - pow(b, \frac{N}{2})^2 & otherwise + b & n = 1 \\ + pow(b, \frac{n}{2})^2 & otherwise \end{array} \right. \] @@ -1226,8 +1222,8 @@ \subsubsection{尾递归} \begin{itemize} \item For the trivial case, that $n$ is zero, the result is 1; -\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. -\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. +\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. +\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. \end{itemize} Below equation formalizes this description. @@ -1236,9 +1232,9 @@ \subsubsection{尾递归} pow(b, n) = \left \{ \begin{array} {r@{\quad:\quad}l} - 1 & N = 0 \\ - pow(b, \frac{N}{2})^2 & 2 | N \\ - b \times pow(b, N-1) & otherwise + 1 & n = 0 \\ + pow(b, \frac{n}{2})^2 & 2 | n \\ + b \times pow(b, n-1) & otherwise \end{array} \right. \ee @@ -1250,22 +1246,22 @@ \subsubsection{尾递归} pow(b, n) = \left \{ \begin{array} {r@{\quad:\quad}l} - 1 & N = 0 \\ - pow(b^2, \frac{N}{2}) & 2 | N \\ - b \times pow(b, N-1) & otherwise + 1 & n = 0 \\ + pow(b^2, \frac{n}{2}) & 2 | n \\ + b \times pow(b, n-1) & otherwise \end{array} \right. \ee -With this change, it's easy to get a tail-recursive algorithm as the following, so that $b^N = pow'(b, N, 1)$. +With this change, it's easy to get a tail-recursive algorithm as the following, so that $b^n = pow'(b, n, 1)$. \be -pow'(b, N, A) = \left \{ +pow'(b, n, A) = \left \{ \begin{array} {r@{\quad:\quad}l} - A & N = 0 \\ - pow'(b^2, \frac{N}{2}, A) & 2 | N \\ - pow'(b, N-1, A \times b) & otherwise + A & n = 0 \\ + pow'(b^2, \frac{n}{2}, A) & 2 | n \\ + pow'(b, n-1, A \times b) & otherwise \end{array} \right. \ee @@ -1273,7 +1269,7 @@ \subsubsection{尾递归} Compare to the naive brute-force algorithm, we improved the performance to $O(\lg n)$. Actually, this algorithm can be improved even one more step. -Observe that if we represent $n$ in binary format $N = (a_ma_{m-1}...a_1a_0)_2$, we clear know +Observe that if we represent $n$ in binary format $n = (a_ma_{m-1}...a_1a_0)_2$, we clear know that the computation for $b^{2^i}$ is necessary if $a_i = 1$. This is quite similar to the idea of Binomial heap (reader can refer to the chapter of binomial heap in this book). Thus we can calculate the final result by multiplying all of them for bits with value 1. @@ -1293,12 +1289,12 @@ \subsubsection{尾递归} Summarize this idea, we can improve the algorithm as below. \be -pow'(b, N, A) = \left \{ +pow'(b, n, A) = \left \{ \begin{array} {r@{\quad:\quad}l} - A & N = 0 \\ - pow'(b^2, \frac{N}{2}, A) & 2 | N \\ - pow'(b^2, \lfloor \frac{N}{2} \rfloor, A \times b) & otherwise + A & n = 0 \\ + pow'(b^2, \frac{n}{2}, A) & 2 | n \\ + pow'(b^2, \lfloor \frac{n}{2} \rfloor, A \times b) & otherwise \end{array} \right. \ee @@ -1307,8 +1303,8 @@ \subsubsection{尾递归} which is the lowest bit) is 0, it means $n$ is even. It goes on computing the square of the base, without accumulating the 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 accumulates it to the product $A$; The edge case is when $n$ is zero, which means we exhaust all the bits in $n$, thus -the final result is the accumulator $A$. At any time, the updated base number $b'$, the shifted exponent number $N'$, -and the accumulator $A$ satisfy the invariant that $b^N = b'^{N'}A$. +the final result is the accumulator $A$. At any time, the updated base number $b'$, the shifted exponent number $n'$, +and the accumulator $A$ satisfy the invariant that $b^n = b'^{n'}A$. This algorithm can be implemented in Haskell like the following.