〖数学算法〗大数模幂运算快速算法

有朋友问我的博文《素性测试》中的Miller-Rabin算法的大数模幂运算快速算法怎么理解,由于在《素性测试》中没有讲解算法原理,所以在此单独一个篇文章详细讲这个算法。这是一个在密码学中比较重要的算法,在我的《素性测试》一文则是用于实现费马小定理。

首先我们先把问题简化一下,看看如何快速求a^b.

先看看我们熟知的两个数学公式:

a^(2c) = (a^c)^2;

a^(2c+1) = a*((a^c)^2);

我们就利用这两个数学公式来解决这个问题,比如a=3,b=13时,我们把b写成二进制的形式13(10)=1101(2),我们从低位到高位运算,每运算一位可以将b右移一位,上面的例子可以转化成3^13 = 3^1 * 3^4 * 3^8,结合上面的两个数学公式我们可以写出如下的代码:

代码清单:

public class MyPow {
	
	public static void main(String[] args){
		 
		int a = 3;
		int b = 13;
		int m = pow(a,b);
		System.out.println(m);
	}

	private static int pow(int a, int b) {
		int result = 1;
		while(b > 0){
			
			if((b & 1) == 1)//b的某位上为1时才累乘
				result *= a;
			
			a *= a;//数学公式所得
			b >>= 1;//右移1位
		}
		return result;
	}
}
如上面的叙述叙述中可以看出快速pow算法的时间复杂度取决于b的二进制位数,而传统的一位一位累乘的pow算法的时间复杂度取决于b的大小,例如上述例子中,两种算法的运算次数分别为4次,和13次。随着b的增大,效率上的差距是显然的。


下面进入我们的主题---大数模幂运算快速算法(a^b % m)

要计算这个,我们首先还要知道一个数学公式:

a^b % m = (...((a % m) * a) % m) ......* a) % m其中a%m有b个

下面我还用上面b=13的例子,利用这个公式来证明下

a^13 % m = ((a^8) % m) * ((a^4) % m) * ((a^1) % m)

证明:

a^b % m = (...((a % m) * a) % m) ......* a) % m其中a%m有b个得

a^8 % m = (...((a % m) * a) % m) ......* a) % m其中a%m有8个

a^4 % m = (...((a % m) * a) % m) ......* a) % m其中a%m有4个

a^1 % m = (...((a % m) * a) % m) ......* a) % m 其中a%m有1个

所以((a^8) % m) * ((a^4) % m) * ((a^1) % m) =  (...((a % m) * a) % m) ......* a) % m 其中a%m有13个 a^13 % m

证毕。


由上面我们证明的公式和第一个pow的例子,容易写出代码如下:

代码清单:

int runFermatPow(int a, int b, int m){
		
		int result = 1;
		while (b > 0) {
			if ((b & 1) == 1)
				result = (result * a);

			a = (a * a) % m;
			b >>= 1;
		}
		return result % m;
}

解释:当b=1101(2)时,从第1位开始result累乘,a = (a*a)%m加上循环可以看成表达式(a%m)^2 % m....因为(a%m)^2 % m = a^2 % m ,所以我们可以把a^13%m看成((a^1) % m) ,((a^4) % m) ,((a^8) % m)的累乘,最后对m取模


但累乘很容易造成溢出,所以我们可以把代码改成如下形式:

代码清单:

int runFermatPow(int a, int b, int m){
		
		int result = 1;
		while (b > 0) {
			if ((b & 1) == 1)
				result = (result * a) % m;

			a = (a * a) % m;
			b >>= 1;
		}
		return result;
}



==================================================================================================

  作者:nash_  欢迎转载,与人分享是进步的源泉!

  转载请保留原文地址http://blog.csdn.net/nash_/article/details/8491301

===================================================================================================

  • 14
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
快速幂运算是一种常用的数学计算方法,用于求解大数幂运算问题。它的原理基于数学中的取运算和幂运算,而快速幂运算则是求解幂运算的一种高效的方法。 首先,我们需要了解以下两个数学概念: 1. 取运算:取运算就是将一个数除以另一个数后所得到的余数。例如,5除以2的余数为1,即5 mod 2 = 1。 2. 幂运算幂运算就是将一个数乘以自己若干次的结果。例如,2的3次方等于8,即2^3 = 8。 接下来,我们来讲解快速的原理和过程: 假设要求解 a^b mod c 的值,其中 a、b、c 均为正整数,其中 b 可以非常大,达到几百万甚至更大,此时计算 a^b mod c 的常规方法是直接计算 a 的 b 次方,然后再对 c 取。这种方法的时间复杂度是 O(b)。如果 b 很大,计算时间就会很长,效率很低。 快速算法的核心思想是利用幂运算的性质和取运算的性质将 b 分解为若干个二进制位,然后对每个二进制位进行计算。具体过程如下: 1. 将 b 转换为二进制数,例如,b=13,二进制表示为:1101。 2. 从右往左扫描二进制数,对于每一位,若该位为 1,则将对应的幂运算结果乘到最终结果中,否则直接忽略。 3. 在计算过程中,用已经计算出来的结果不断平方,然后对 c 取,这样可以避免重复计算,提高计算效率。 举个例子,我们要计算 2^13 mod 7 的值,可以使用快速算法进行计算: 1. 将 13 转换为二进制数,即 13 = 1101。 2. 从右往左扫描二进制数,对于每一位,若该位为 1,则将相应的幂运算结果乘到最终结果中,否则直接忽略。计算过程如下: - 2^1 mod 7 = 2 - 2^2 mod 7 = 4 - 2^4 mod 7 = 2 - 2^8 mod 7 = 4 - 2^13 mod 7 = 2 * 4 * 2 * 4 * 2 mod 7 = 8 mod 7 = 1 因此,2^13 mod 7 的值为 1。 快速算法是求解幂运算的一种高效的方法,其核心思想是利用幂运算的性质将指数进行二进制分解,然后利用分治思想进行计算。具体过程如下: 1. 将指数 b 转化成二进制数,例如,b=13,二进制表示为:1101。 2. 从右往左扫描二进制数,对于每一位,若该位为 1,则将底数 a 的对应次方乘到最终结果中,否则直接忽略。 3. 在计算过程中,用已经计算出来的结果不断平方,这样可以避免重复计算,提高计算效率。 举个例子,我们要计算 2^13 的值,可以使用快速算法进行计算: 1. 将 13 转换为二进制数,即 13 = 1101。 2. 从右往左扫描二进制数,对于每一位,若该位为 1,则将相应的幂运算结果乘到最终结果中,否则直接忽略。计算过程如下: - 2^1 = 2 - 2^2 = 4 - 2^4 = 16 - 2^8 = 256 - 2^13 = 2 * 4 * 16 * 256 * 2 = 32768 因此,2^13 的值为 32768。 快速算法快速算法都是常用的数学计算方法,在实际应用中经常被使用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值