2.7-2.8 数值自乘求解 C实现

该问题出自《C语言名题精选百则技巧篇》

题目:如果n和m是正整数,求m^n.

m^n就是把m连乘n次,这是一个很没有效率的方法,我们要找到更有效率的办法。

第一种方法  递归

很容易可以注意到,x^4可以写成x^2 * x^2,  通过x*x*x*x的方法要进行3次乘法,而x^2 * x^2只需要进行两次乘法,可以减少乘法运算的数量。因此我们可以把x^m里边偶数次幂的部分分离出来。

m^n = 1                 n=0

m^n = (m^k)^2       n=2k(偶数)

m^n = m*m^2k      n=2k+1(奇数)

用递归函数也可以分成三个部分,第一部分看n是否为0,;第二部分看n是否是偶数,如果是,就求m的n/2次方(递归),算出来的结果再平方就是m^n.

;当n是个奇数时,n=2k+1,m*m^2k,递归调用自己去计算m^2k,依此写出的函数为recursive_power()函数。

第二种方法 非递归方法

可以把m^n的幂数n转化成二进制,比如n=45,则45 = 101101 = 1*2^5+0*2^4+1*2^3+1*2^2+0*2^1+1*2^0。则

m^n = m^(2^5)* m^(2^3) * m^(2^1) * m^(2^0)值为1的那一位(比如第i位,从右往左为0,1,2,3),在m的指数中就有m^(2^i)那一项,因此我们可以把m^(2^0),m^(2^1),m^(2^2),...,m^(2^(i+1)).求出来,这正好对应着n的二进制表示中,从右到左的顺序,如果在n的二进制表示中第i位是1,那么就把m^(2^i)乘到一个用来保存最终结果的变量中(初值为1),因此当n的每一位都查完以后,就有了答案了。

    如何求m^(2^0),m^(2^1),m^(2^2),...,m^(2^i)?

    m^(2^(i+1)) = m^((2^i)*2) = (m^(2^i))^2.因此只要求出m^(2^i),就能得到  m^(2^(i+1)) 。

    比如n=45=101101, temp初始为1

      n最低位为1,temp = temp*m = m,使n右移一位n = 10110,m=m*m= m^2,

      n最低位为0,temp不变,n右移一位n=1011,m=m*m = m^2 *m^2 = m^4

      n最低位为1,temp = temp*m = m^5,n右移一位n=101,m=m*m = m^4 *m^4 = m^8

      n最低位为1,temp = temp*m = m^13,n右移一位n=10,  m=m*m = m^8 *m^8 = m^16 

      n最低位为0,temp 不变,n右移一位n=1,m=m*m = m^16 *m^16= m^32

      n最低位为1,temp = temp*m = m^45. n右移一位,n=0结束。

     依此写出的函数为iterative_power()函数。


#include <stdio.h>
#include <stdlib.h>
unsigned long recursive_power(unsigned long m,unsigned long n)
{
	unsigned long temp;
	if(n==0)
	    return 1;
	else if(n%2==0){
	    temp = recursive_power(m,n/2);
	    return temp*temp;
	}else 
	    return m*recursive_power(m,n-1);
}
unsigned long iterative_power(unsigned long m,unsigned long n)
{
	unsigned long temp =1;	
	while(n>0){
	    if(n&0x01UL == 1)
	        temp *=m;
	    m*=m;
	    n>>=1;
	}
	return temp;
}
int main(int argc,char *argv[])
{
	int m,n;
	unsigned long answer;
	printf("\nR_POWER  Program:m^n");
	printf("\nInput m -->");
	scanf("%d",&m);
	printf("Input n -->");
	scanf("%d",&n);
	//answer = recursive_power(m,n);
	answer = iterative_power(m,n);
	printf("m^n = %d^%d = %ld",m,n,answer);
	while(1)
	    getchar();
	return 0;
	
}

运算结果




                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值