在power算法中求一个数x的n次方分成两部分,一是当n为偶数时计算方法,另一部分是当n为奇数时的计算方法。在n的"分解"过程中,还可能还会出现偶数和奇数部分的代码都参与计算。
n为偶数,计算方式:
假设 Y = x*x , Z = n / 2;
那么xn = YZ。例如如下步骤:
28 = 44。 (1)
44 = 162。 (2)
162 = 2561。(3) // 此时n == 1,即结果最终转换成了一个数的奇次方。
while ((n & 1) == 0) { // 当一个数的第0位为0,表示此数是偶数。
n >>= 1; // 等价于指数n除2
x = op(x, x);
}
n为奇数,计算方式:
公式:xn = xn-1 * x。既然n此时为奇数,那么n-1就为偶数了。例如如下步骤:
27 =26 * 2。 (1)
26 * 2 = 43* 2。 (2)
43* 2 = (42 * 4) * 2 = 42 * (4 * 2) = 42 * 8。 (3)
42 * 8 = 161 * 8。 (4)
T result = x; // 步骤(1)被隐含执行了
n >>= 1;
while (n != 0) {
x = op(x, x);
if ((n & 1) != 0) // 第0位为1是奇数。n为奇数,则执行特定操作,如上面的步骤(3)
result = op(result, x);
n >>= 1;
}
n为较特殊的偶数情况:
如当x为2,n为14时。执行偶数如下
214 = 47。
执行上面操作后,变为x是4,n是7的计算方式,也就是我们可以认为值的计算已被转换成了n为奇数情形的计算方式了。
最后注意对stl中的这算法不必局限于纯数学运算--注意泛型中所提到的connect。
- template <class T, class Integer, class MonoidOperation>
- T power(T x, Integer n, MonoidOperation op) {
- if(n == 0)
- return x;
- else {
- while((n & 1) == 0) {
- x = op(x, x);
- n >>= 1;
- }
- T result = x;
- n >>= 1;
- while(n != 0) {
- x = op(x, x);
- if((n & 1) != 0)
- result = op(result, x);
- n >>= 1;
- return result;
- }
- }