SICP-求幂

【问题】

对一个给定的数计算乘幂问题。

【思路1】

对一个基数b和一个正整数的指数n,计算出b^n的过程。可以通过下面的这个递归定义:

b^n = b * b ^(n-1)

b^0 = 1

直接翻译为如下过程:

(define (expt b n)
   (if (= n 0)
        1
        (* b (expt b (- n 1)))))

这是一个线性的递归计算过程,需要THETA(n)步和THETA(n)空间。我们可以很容易将其形式化为一个等价的线性迭代:

(define (expt b n)
     (expt-iter b n 1))
(define (expt-iter b counter product)
   (if (= counter 0)
       product
       (expt-iter b
                  (- counter 1)
                  (* product b))))

这个版本需要THETA(n)步和THETA(1)空间。

【思路2】

采用如下规则完成乘幂计算:

b^n = (b^(n/2))^2    若n是偶数

b^n = b * b^(n-1)  若n是奇数

这一方法可以定义为如下的过程:

(define (fast-expt b n)
   (cond ( (= n 0) 1)
         ( (even? n) (square (fast-expt b (/ n 2))))
         (else (* b (fast-expt (b (- n 1)))))))
(define (even? n)
   (= (remainder n 2) 0))  

这一计算过程只需要THETA(log n)步。

迭代方式的求幂计算过程:

(define (fast-expt b n)
    (expt-iter b n 1))
(define (expt-iter b n a)
    (cond ( (= n 0 ) a)
          ( (even? n) (expt-iter (square b) (/ n 2) a))
          ( (odd? n) (expt-iter b (- n 1) (* b a)))))

采用不同的方式实现时,我们考虑规则的角度会很不一样。

递归方式: b^n = (b^(n/2))^2  若n是偶数

迭代方式:b^n = (b^2)^(n/2)   若n是偶数

SICP-求幂

时间: 2024-10-15 08:06:41

SICP-求幂的相关文章

求幂运算、多项式乘法及Horner法则的应用

一,两种不同的求幂运算 求解x^n(x 的 n 次方) ①使用递归,代码如下: 1 private static long pow(int x, int n){ 2 if(n == 0) 3 return 1; 4 if(n == 1) 5 return x; 6 if(n % 2 == 0) 7 return pow(x * x, n / 2); 8 else 9 return pow(x * x, n / 2) * x; 10 } 分析: 每次递归,使得问题的规模减半.2到6行操作的复杂度为

二分求幂,快速求解a的b次幂

一个引子 如何求得a的b次幂呢,那还不简单,一个for循环就可以实现! void main(void) { int a, b; int ans = 1; cin >> a >> b; for (int i = 1; i <= b; i++) { ans *= a; } cout << ans; } 那么如何快速的求得a的b次幂呢?上面的代码还可以优化吗? 当然是ok的!下面就介绍一种方法-二分求幂. 二分求幂 所谓二分求幂,即是将b次幂用二进制表示,当二进制位k位

A sequence of numbers(快速求幂)

题目描述 Xinlv wrote some sequences on the paper a long time ago, they might be arithmetic or geometric sequences. The numbers are not very clear now, and only the first three numbers of each sequence are recognizable. Xinlv wants to know some numbers in

NYOJ--102--次方求模(快速求幂取模)

次方求模 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 求a的b次方对c取余的值 输入 第一行输入一个整数n表示测试数据的组数(n<100)每组测试只有一行,其中有三个正整数a,b,c(1=<a,b,c<=1000000000) 输出 输出a的b次方对c取余之后的结果 样例输入 3 2 3 5 3 100 10 11 12345 12345 样例输出 3 1 10481 1 /* 2 Name: NYOJ--102--次方求模 3 Copyright: ?

快速求幂

快速幂在算指数时是很高效的,他的基本原理是二进制. 如果要算 2^5,可以直接2*2*2*2*2 但是如果要算 3^999,指数N太大,计算太慢,所以有一种快速的解法. @@@@@@@@@@@@@@@@@@@@@@@@ 以3^21为例. 2^21=(2^16)×(2^4)×(2^1) 21的二进制可以写成(10101)----------------而10101可以写成1*2^4+0*2^3+1*2^2+0*2^1+1*2^0 可以明显看出, 每一个香对应着上边的指数.   2^4=16 2^2

快速求幂运算笔记

如何快速求x得n次方呢? 首先C++里面有个pow如何实现呢?自己查查,里面使用double,肯定更麻烦,还有jianzhi 我们会顺手写下 int res=1; for(int i=1;i<=n;i++) { res*=x; } 学习一下快速幂,logn内计算出来,使用N的二进制,只需要logN就可以计算. 正要的就是计算每个为1对应的基数.列入: 11是多少?是二进制的话,就是1*2^1+1 那么x^(11)呢,两个1对应的基数是多少呢?低位1对应的是X,高位1对应的是X^2,因此,就是位于

二分求幂(快速求幂,二进制求幂)

二分求幂, 非递归求法(二进制求法): 比如 2^5就是5个2相乘,按照5的二进制求 3^10就是8个3相乘,再2个3相乘. 处理幂的二进制,具体实现代码如下: long long quickmulti(long long a,long long b) { long long res=1; while(b) { if(b&1) //如果最后一位为1,则res*=a; res*=a; a*=a; //a*=a b>>=1; //b%=2 } return res; }

整数求幂

问题描述:求一个整数的n次幂,对m取余. 思路一:简单循环 1 int Pow(int num, int n, int m) 2 { 3 int res = 1; 4 5 while (n--) { 6 res *= num; 7 } 8 9 return res % m; 10 } 以上代码有个隐患,当n足够大的时候,res会溢出,因此需要优化. 有这样一个公理:两个数的积对另一个数取余,等于这两个数分别对第三个数取余的乘积再对第三个数取余.也就是a*b%c = (a%c)*(b%c)%c 根

求幂算法

1.简单递归 最简单的求幂算法是根据xn=x*xn-1,使用递归: def foo(x,n): if n==0: return 1 else: return x*foo(x,n-1) 这样求x的n次方,会进行n-1次乘法运算,n较大时效率很低. 2.高效递归 一种更高效的算法,可以将运算次数降到LogN的级别,由于: xn=xn/2*xn/2 , n为偶数时 xn=x(n-1)/2*x(n-1)/2*x , n为奇数时 def foo(x,n): if n==0: return 1 else:

高效求幂运算

//说明: //高效求幂运算(递归) //输入:整数X,幂次N //输出:X^N //时间复杂度:O(logN) #include<iostream> using namespace std; int Pow(int X,int N) { if(N==0) return 1; else if(N==1) return X; else if(N%2==0) return Pow(X*X,N/2); else return Pow(X*X,N/2)*X; } void main() { cout&