实验目的与要求
- 利用扩展欧几里得定理计算乘法逆元。
- 理解并掌握中国剩余定理。
原理
实验内容
实验步骤与结果
实现本次实验所用的环境为jdk1.8下的Java代码,代码测试结果在最下面。
由于扩展欧几里得定理和中国剩余定理都要基于求最大公因数的方法getGcd()
,这里附上相关代码:
/**
* 最大公因数计算方法:辗转相除法
* @param a
* @param b
* @return 最大公因数
*/
public static int getGcd(int a,int b){
int gcd = 1;
if (a < b){
//若传入a小于b,交换a和b的值(不用定义一个新变量,节省空间)
a = a + b;
b = a - b;
a = a - b;
}
if (a % b == 0){
//如果a mod b为0,则b为最大公约数
gcd = b;
}
while (a % b > 0){
a = a % b;
if (a < b) {
a = a + b;
b = a - b;
a = a - b;
}
if (a % b == 0) {
gcd = b;
}
}
return gcd;
}
扩展欧几里得定理的实现方法(函数)inverse()
:
/**
* 扩展欧几里得算法
* @param p 模p乘法
* @param a 模p乘法群中的任一元素
* @return a的乘法逆元
*/
public static int inverse(int p,int a) {
int[] m = {1,0,p};
int[] n = {0,1,a};
int[] temp = new int[3];
int q = 0; //初始化
boolean flag = true;
while(flag) {
q = m[2] / n[2];
for(int i = 0;i < 3;i++) {
temp[i] = m[i] - q * n[i];
m[i] = n[i];
n[i] = temp[i];
}
if(n[2] == 1) {
if(n[1] < 0)
{
n[1] = n[1] + p;
}
return n[1];
}
if(n[2] == 0){
flag = false;//无逆元,跳出循环
}
}
return 0;
}
中国剩余定理实现方法(函数)CRT()
:
/**
* 中国剩余定理实现函数
* @param m 同余方程组的除数
* @param a 同余方程组的被除数
* @return 同余方程组的解 A (余数)
*/
public static int CRT(int[] m,int[] a){
int A = 0;
int M = 1;
int[] m1 = new int[m.length];//存放m的乘法逆元
int[] m2 = new int[m.length];
for (int i = 0;i < m.length;i++){
M *= m[i];
m2[i] = m[i];//复制一个mi数组
}
for (int i = 0;i < m.length;i++){
m[i] = M / m[i];
m1[i] = inverse(m2[i],m[i]);//求出m[i]的逆元
A += a[i] * m[i] * m1[i];
}
return A % M;
}
测试方法:放在主方法 main()
中测试
//main方法
public static void main(String[] args) {
//验证getGcd方法
System.out.println(getGcd(24140,16762));//34
//验证扩展欧几里得算法
System.out.println(inverse(49,37));//37的乘法逆元:4
System.out.println(inverse(37,49));//49的乘法逆元:34
//验证中国剩余定理
int[] a = {11,42};
int[] m = {37,49};
System.out.println(CRT(m, a));//973
}
实验结论
通过本次实验,我对使用扩展欧几里得定理求逆元的原理有了更进一步的理解并且能对其加以运用,同时也更深刻认识到了中国剩余定理的原理与运用,学习到了利用中国剩余定理求一次同余方程组的解,除此之外,也使我对Java语言的使用更加熟练。