中国剩余定理
一、实验目的
实验环境:python环境
实验目标:实现中国剩余定理,计算同余方程组的解
二、方案设计
(一)背景
中国剩余定理(即孙子定理)是中国古代求解一次同余式组的方法。是数论中一个重要定理。一元线性同余方程组问题最早可见于中国南北朝时期(公元5世纪)的数学著作《孙子算经》卷下第二十六题,叫做“物不知数”问题,原文如下:
有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二。问物几何?即,一个整数除以三余二,除以五余三,除以七余二,求这个整数。
《孙子算经》中首次提到了同余方程组问题,以及以上具体问题的解法,因此在中文数学文献中也会将中国剩余定理称为孙子定理。
(二)实验原理
(三)算法步骤
三、方案实现
(二)算法主要代码
# 扩展欧几里得算法,返回值列表中,x是a的逆元(mod b),q是gcd(a,b),若x是0,则表示没有逆元
def Ex_Euclid(a, b):
if 0 == b:
x = 1;
y = 0;
q = a
return x, y, q
xyq = Ex_Euclid(b, a % b)
x = xyq[0];
y = xyq[1];
q = xyq[2]
temp = x;
x = y;
y = temp - a // b * y
return x, y, q
# 获取a的逆元(mod b)的函数,目的是为了封装获取逆元的功能
def Get_Inverse(a, b):
return Ex_Euclid(a, b)[0]
# 获取a和b的最大公约数函数
def gcd(a, b):
return Ex_Euclid(a, b)[2]
# 判断所有的mi是否两两互质
def Is_Coprime(m_list):
for i in range(len(m_list)):
for j in range(i + 1, len(m_list)):
if 1 != gcd(m_list[i], m_list[j]):
return 0 # 返回0表示不是两两互质的
return 1 # 返回1表示是两两互质的
# 获取所有的Mi
def Get_Mi(m_list, M):
Mi_list = []
for mi in m_list:
Mi_list.append(M // mi)
return Mi_list
# 获取所有的Mi的逆元
def Get_Mi_inverse(Mi_list, m_list):
Mi_inverse = []
for i in range(len(Mi_list)):
Mi_inverse.append(Get_Inverse(Mi_list[i], m_list[i]))
return Mi_inverse
# 中国剩余定理,返回值为最终的x
def C_R_T(path):
# 两个空列表,分别用来保存mi和bi
m = {}
b = {}
file_object = open(path, 'r')
i = 1
for i in [1, 2, 3]:
b[i] = file_object.readline()
for i in [1, 2, 3]:
m[i] = file_object.readline()
m_list = []
b_list = []
for i in [1, 2, 3]:
temp = int(b[i])
b_list.append(temp)
for i in [1, 2, 3]:
temp = int(m[i])
m_list.append(temp)
if 0 == Is_Coprime(m_list):
print("错误!输入的mi并不是两两互素的,不能直接使用中国剩余定理\n")
return 0
M = 1 # M是所有mi的乘积
for m in m_list:
M *= m
Mi_list = Get_Mi(m_list, M)
Mi_inverse = Get_Mi_inverse(Mi_list, m_list)
x = 0
for i in range(len(b_list)): # 开始计算x
x += Mi_list[i] * Mi_inverse[i] * b_list[i]
x %= M
return x
if __name__ == '__main__':
print('结果: 1.txt:')
path1 = '1.txt'
t = C_R_T(path1)
if t != 0:
print("同余式组的解为:x=", t)
print('结果: 3.txt')
path2 = '3.txt'
t = C_R_T(path2)
if t != 0:
print("同余式组的解为:x=", t)
四、思考与总结