【发布时间】:2020-07-21 19:32:48
【问题描述】:
我正在寻找一种比我在 stackoverflow 上找到的更好的算法来处理 4096 字节数,我正在达到最大递归深度。
来自 stackoverlow 帖子的代码,我复制/粘贴它但丢失了原始链接:
def linear_congruence(a, b, m):
if b == 0:
return 0
if a < 0:
a = -a
b = -b
b %= m
while a > m:
a -= m
return (m * linear_congruence(m, -b, a) + b) // a
这适用于较小的数字,例如:
In [167]: pow_mod(8261, 63, 4033)
63 1 8261 4033
31 195 1728 4033
15 2221 1564 4033
7 1231 2098 4033
3 1518 1601 4033
1 2452 2246 4033
0 2147 3266 4033
Out[167]: 2147
And the linear congruence works:
linear_congruence(8261, 3266, 4033):
2147
但是我用更大的数字达到了最大递归深度。我提供的linear_congruence算法有更好的算法还是非递归算法?
根据 Eric Postpischil 的评论,我从维基百科条目中编写了伪代码,并利用此处的方法创建了一个非常快速的线性同余算法:http://gauss.math.luc.edu/greicius/Math201/Fall2012/Lectures/linear-congruences.article.pdf。
这很适用于幂为 2-1 的 pow,以获得答案。我正在研究如何抵消这会改变答案,并希望将其纳入这些答案,但现在,我有我需要的东西,因为我正在使用 2 -1 的幂 for y in pow( x, y, z):
def fastlinearcongruencex(powx, divmodx, N, withstats=False):
x, y, z = egcditerx(powx, N, withstats)
if x > 1:
powx//=x
divmodx//=x
N//=x
if withstats == True:
print(f"powx = {powx}, divmodx = {divmodx}, N = {N}")
x, y, z = egcditerx(powx, N)
if withstats == True:
print(f"x = {x}, y = {y}, z = {z}")
answer = (y*divmodx)%N
if withstats == True:
print(f"answer = {answer}")
return answer
def egcditerx(a, b, withstats=False):
s = 0
r = b
old_s = 1
old_r = a
while r!= 0:
quotient = old_r // r
old_r, r = r, old_r - quotient * r
old_s, s = s, old_s - quotient * s
if withstats == True:
print(f"quotient = {quotient}, old_r = {old_r}, r = {r}, old_s = {old_s}, s = {s}")
if b != 0:
bezout_t = quotient = (old_r - old_s * a) // b
if withstats == True:
print(f"bezout_t = {bezout_t}")
else:
bezout_t = 0
if withstats == True:
print("Bézout coefficients:", (old_s, bezout_t))
print("greatest common divisor:", old_r)
return old_r, old_s, bezout_t
它甚至可以立即处理 4096 字节的数字,这很棒:
In [19036]: rpowxxxwithbitlength(1009,offset=0, withstats=True, withx=True, withbl=True)
63 1 272 1009
31 272 327 1009
15 152 984 1009
7 236 625 1009
3 186 142 1009
1 178 993 1009
0 179 256 1009
Out[19036]: (179, 256, True, 272)
In [19037]: fastlinearcongruencex(272,256,1009)
Out[19037]: 179
感谢 Eric 指出这是什么,我使用 egcd 和上面 pdf 中的过程编写了一个非常快速的线性同余算法。如果任何 stackoverflowers 需要快速算法,请将它们指向这个。我还了解到,当 pow(x,y,z) 的 y 偏离 2-1 的幂时,始终保持一致。我会进一步调查,看看是否存在偏移更改以保持答案完整,如果找到,我会在未来跟进。
【问题讨论】:
-
你提前知道
a与m互质吗?如果没有,您希望如何处理涉及多个解决方案或没有解决方案的案例? -
如果我能得到多种解决方案,那就太好了,我注意到它不是 100%,所以我很高兴听到有多种解决方案。我只将它用于 pow mod 的数字,所以我还没有看到没有解决方案的情况,所以我不确定我想如何处理这些,也许只是没有答案。现在,如果我没有得到正确的答案,我会做上面的下一个数字,通常会奏效。
-
另外,我不知道 a 与 m 互质。我正在使用算法来生成 a,并从事个人教育数学项目,看看我是否可以制定可以预测最后一个模数 x 的数字。我知道,这听起来不可能,但这是一个有趣的项目,我在做一些听起来不可能的事情时很开心:-)
-
将代码重写为循环,而不是递归调用。这是Extended Euclidean Algorithm,不应使用递归编写。
-
来源很可能是this answer。
标签: python math linear-programming modulus mod