Java实现欧几里得算法和拓展欧几里得算法

写在前面

欧几里得算法 (gcd(a,b)) 是一个求解最大公因数的算法。比如:
gcd(42,30) = 6;
所谓 gcd,就是greatest common divisor ,最大公因数
欧几里得算法是直接求得 gcd(a,b)的值,根据中学的数学知识,我们可以得到 gcd(a,b)=gcd(b,a mod b);
这里的 mod 代表的是 取余操作。 实际上 欧几里得算法与我们学过的辗转相除法的原理是类似的,这里不做过多叙述。代码也比较简单,直接使用递归方法就可以实现。

   /**
     *
     * @param a 第一个参数
     * @param b 第二个参数
     * @return 返回值 最大公因数
     */
    public static long gcd(long a, long b){
        if(b==0){
            return a;
        }
        return gcd(b, a%b);
    }

而 拓展欧几里得算法 则是除了得到最大公因数之外还要得到满足 ax + by = gcd(a,b) 的 x,y值
这里我们可以假设在每个步骤i中都周到 xi 和 yi都满足ri=axi+byi;
也就是可以得到如下式子:
Java实现欧几里得算法和拓展欧几里得算法_第1张图片
经过推到可以得到:
Java实现欧几里得算法和拓展欧几里得算法_第2张图片
(两个图片截取于书籍《密码编码学与网络安全》)
了解数学原理之后,这里直接插入代码:

 /**
   *
   * @param a 第一个参数
   * @param b 第二个参数
   * @param x x的值,前两个组成的数组
   * @param y y的值,前两个组成的数组
   * @return 返回值为 {最大公约数,x的值,y的值}
   */
  public static long[] ex_gcd(long a, long b, long[] x, long[] y){

      long gcd;
      long[] result = new long[3];

      if(b==0){
          result[0] = a;
          result[1] = x[0];
          result[2] = y[0];
          return result;
      }
      long q=a/b;
      long tx1 = x[0]-q*x[1];
      long ty1 = y[0]-q*y[1];
      long[] tx = {x[1],tx1};
      long[] ty = {y[1],ty1};
      return ex_gcd(b,a%b,tx,ty);
  }

  public static long[] ex_gcd(long a, long b){
      long[] x = {1,0};
      long[] y = {0,1};
      return ex_gcd(a,b,x,y);
  }

这样可以调用main方法实现求解:

Java实现欧几里得算法和拓展欧几里得算法_第3张图片

乘法逆元:是指数学领域群G任意一个元素a,都在G中有唯一的逆元a’,具有性质 a x a’ = a’ x a = e;e代表该群的单位元。

例如:4关于1模9的惩罚逆元:
4X ≡ 1 mod 9.那么这个方程等价于求一个X和K,满足:
4X mod 9 = 1 mod 9 = 1
也就是:4X = 9K + 1
其中 X 和 K 都是整数
若 aX ≡ 1 mod f,则称 a 关于 1模f 乘法逆元为x,也可表示为 ax ≡ 1 (mod f)

如果a与f互素,那么a关于模f 的乘法逆元有解。如果不互素,则无解。如果f为素数,则从1 到 (f-1)的任意数都与f互素,即在1到 (f-1)之间都恰好有一个关于模f 的乘法逆元

例如: 求 7 关于 模 15的乘法逆元:
15 = 7x2 + 1
所以 15和 7是互素的
1 = 7 x 13 - 15 x 6
所以 7关于 模 15的乘法逆元是 13

你可能感兴趣的:(JavaSE)