python定义一个乘法函数_Python中的模块乘法逆函数

也许有人会觉得这有用(从wikibooks ):

def egcd(a, b): if a == 0: return (b, 0, 1) else: g, y, x = egcd(b % a, a) return (g, x - (b // a) * y, y) def modinv(a, m): g, x, y = egcd(a, m) if g != 1: raise Exception('modular inverse does not exist') else: return x % m

如果你的模数是素数(你称之为p ),那么你可以简单地计算:

y = x**(p-2) mod p # Pseudocode

或者正确的Python:

y = pow(x, p-2, p)

这里是一些在Python中实现了一些数字理论function的人: http : //userpages.umbc.edu/~rcampbel/Computers/Python/numbthy.html

以下是在提示符下完成的示例:

m = 1000000007

x = 1234567

y = pow(x,m-2,m)

ÿ

989145189L

X * Y

1221166008548163L

x * y%m

1L

你可能也想看看gmpy模块。 它是Python和GMP多精度库之间的接口。 gmpy提供了一个反转function,完全符合你的需求:

>>> import gmpy >>> gmpy.invert(1234567, 1000000007) mpz(989145189)

更新了答案

正如@hyh指出的那样,如果反函数不存在, gmpy.invert()将返回0。 这符合GMP的mpz_invert()函数的行为。 gmpy.divm(a, b, m)为a=bx (mod m)提供了一个通用的解决scheme。

>>> gmpy.divm(1, 1234567, 1000000007) mpz(989145189) >>> gmpy.divm(1, 0, 5) Traceback (most recent call last): File "", line 1, in ZeroDivisionError: not invertible >>> gmpy.divm(1, 4, 8) Traceback (most recent call last): File "", line 1, in ZeroDivisionError: not invertible >>> gmpy.divm(1, 4, 9) mpz(7)

当gcd(b,m) == 1时, divm()将返回一个解gcd(b,m) == 1并且当乘法inverse不存在时引发一个exception。

免责声明:我是gmpy库的当前维护者。

更新了答案2

现在gmpy2在反转不存在时正确地引发exception:

>>> import gmpy2 >>> gmpy2.invert(0,5) Traceback (most recent call last): File "", line 1, in ZeroDivisionError: invert() no inverse exists

这里是CodeFights的单线程 ; 这是最短的解决scheme之一:

MMI = lambda A, n,s=1,t=0,N=0: (n < 2 and t%N or MMI(n, A%n, t, sA//n*t, N or n),-1)[n<1]

如果A在n没有乘法倒数,它将返回-1 。

用法:

MMI(23, 99) # returns 56 MMI(18, 24) # return -1

该解决scheme使用扩展欧几里德algorithm 。

这里是我的代码,它可能是马虎,但似乎无论如何对我工作。

# a is the number you want the inverse for # b is the modulus def mod_inverse(a, b): r = -1 B = b A = a eq_set = [] full_set = [] mod_set = [] #euclid's algorithm while r!=1 and r!=0: r = b%a q = b//a eq_set = [r, b, a, q*-1] b = a a = r full_set.append(eq_set) for i in range(0, 4): mod_set.append(full_set[-1][i]) mod_set.insert(2, 1) counter = 0 #extended euclid's algorithm for i in range(1, len(full_set)): if counter%2 == 0: mod_set[2] = full_set[-1*(i+1)][3]*mod_set[4]+mod_set[2] mod_set[3] = full_set[-1*(i+1)][1] elif counter%2 != 0: mod_set[4] = full_set[-1*(i+1)][3]*mod_set[2]+mod_set[4] mod_set[1] = full_set[-1*(i+1)][1] counter += 1 if mod_set[3] == B: return mod_set[2]%B return mod_set[4]%B

为了找出模乘法逆,我推荐使用这样的扩展欧几里德algorithm:

def multiplicative_inverse(a, b): origA = a X = 0 prevX = 1 Y = 1 prevY = 0 while b != 0: temp = b quotient = a/b b = a%b a = temp temp = X a = prevX - quotient * X prevX = temp temp = Y Y = prevY - quotient * Y prevY = temp return origA + prevY

上面的许多链接是截至2017年1月23日。 我发现这个实现: https : //courses.csail.mit.edu/6.857/2016/files/ffield.py

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值