【问题标题】:prime factorization with large numbers in pythonpython中大数的素数分解
【发布时间】:2018-07-26 07:49:33
【问题描述】:

哇塞,

遇到以下问题,我无法解决。 处理长度在 5 - 52 左右的数字,我不想得到它们的素数。 使用Python,我发现了以下两种算法:

我。

def faktorisiere(n):
    l = []  # Lösungsmenge
    # Auf Teilbarkeit durch 2, und alle ungeraden Zahlen von 3..n/2 testen
    for i in chain([2], range(3, n//2 + 1, 2)):
        # Ein Teiler kann mehrfach vorkommen (z.B. 4 = 2 * 2), deswegen:
        while n % i == 0:
            l.append(i)
            print(i)
            n = n // i  # "//" ist ganzzahlige Division und entspricht int(n/i)
        if i > n:  # Alle Teiler gefunden? Dann Abbruch.
            break
    print(l)

二。

x = input("Number: ")
mode = x[-1:]
x = int(x[:-1])
if int(x) < 1000000000000:
    faktorisiere(x)
else:
    if mode == 'f':
        faktorisiere(x)
    rx = int(sqrt(x)) + 1

    for i in range(1, rx+1):
        if mode == 'a':
            if x % i == 0:
                y = int(x/i)
                print(str(x), "=", i, "*", str(y))
        if mode == 'u':
            if i % 2 != 0:
                if x % i == 0:
                    y = int(x/i)
                    print(str(x), "=", i, "*", str(y))

但是第一个代码计算数字非常慢,如下所示: 1917141215419419171412154194191714

第二个工作得快一点,但我得到错误的输出,我在代码中找不到错误。 作为示例,我们采用给定的数字。 这些是pythons输出的第一行:

  • 1917141215419419171412154194191714 = 1 * 1917141215419419143900621852114944

  • 1917141215419419171412154194191714 = 2 * 958570607709709571950310926057472

  • 1917141215419419171412154194191714 = 3 * 639047071806473023947675938062336

但正如您所见,这些乘法并不等于结果。 代码中是否有任何错误? 或者仅仅是因为数字的长度? 希望你能帮助我。

最好的祝愿, 时间人

【问题讨论】:

  • 因式分解非常大的数字非常困难。没有已知的算法可以快速完成。
  • 我认为在我的情况下,如果它包含几秒钟或几分钟是没有问题的。但我不知道为什么我会得到这些错误的输出。是的,我知道像这样的大数很难分解。真的很伤心,没有人找到有效的算法
  • 这些是舍入错误,请使用 y = x//i 而不是 int(x/y),就像您在算法 I 中所做的那样。
  • 感谢您的建议。所以这就像在不四舍五入结果的情况下精确除法?

标签: python numbers output primes factorization


【解决方案1】:

您需要一种比试除法更好的算法来将数字分解为您正在使用的大小。 John Pollard 的 rho 算法是从试用部门升级的一个简单步骤:

Python 2.7.13 (default, Mar 13 2017, 20:56:15)
[GCC 5.4.0] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def isPrime(n, k=5): # miller-rabin
...     from random import randint
...     if n < 2: return False
...     for p in [2,3,5,7,11,13,17,19,23,29]:
...         if n % p == 0: return n == p
...     s, d = 0, n-1
...     while d % 2 == 0:
...         s, d = s+1, d/2
...     for i in range(k):
...         x = pow(randint(2, n-1), d, n)
...         if x == 1 or x == n-1: continue
...         for r in range(1, s):
...             x = (x * x) % n
...             if x == 1: return False
...             if x == n-1: break
...         else: return False
...     return True
...
>>> def factors(n, b2=-1, b1=10000): # 2,3,5-wheel, then rho
...     def gcd(a,b): # euclid's algorithm
...         if b == 0: return a
...         return gcd(b, a%b)
...     def insertSorted(x, xs): # linear search
...         i, ln = 0, len(xs)
...         while i < ln and xs[i] < x: i += 1
...         xs.insert(i,x)
...         return xs
...     if -1 <= n <= 1: return [n]
...     if n < -1: return [-1] + factors(-n)
...     wheel = [1,2,2,4,2,4,2,4,6,2,6]
...     w, f, fs = 0, 2, []
...     while f*f <= n and f < b1:
...         while n % f == 0:
...             fs.append(f)
...             n /= f
...         f, w = f + wheel[w], w+1
...         if w == 11: w = 3
...     if n == 1: return fs
...     h, t, g, c = 1, 1, 1, 1
...     while not isPrime(n):
...         while b2 <> 0 and g == 1:
...             h = (h*h+c)%n # the hare runs
...             h = (h*h+c)%n # twice as fast
...             t = (t*t+c)%n # as the tortoise
...             g = gcd(t-h, n); b2 -= 1
...         if b2 == 0: return fs
...         if isPrime(g):
...             while n % g == 0:
...                 fs = insertSorted(g, fs)
...                 n /= g
...         h, t, g, c = 1, 1, 1, c+1
...     return insertSorted(n, fs)
...
>>> factors(1917141215419419171412154194191714)
[2, 3, 13, 449941L, 54626569996995593878495243L]

立即返回分解。请参阅 here 以了解其工作原理。要考虑更大的数字,您需要查看椭圆曲线法二次筛之类的算法,但要注意这两种算法都很复杂。

【讨论】:

  • 我对二次筛有一些疑问,听起来并不那么容易,你是对的。最后两个数字后面的L是什么意思?感谢您的代码,我会看看它并尝试了解其中发生了什么。
  • L 用于长整数,太大而无法存储在机器原生整数中。我不确定为什么 449941 被标记为长,但另一个因素肯定是长。
  • 感谢 user448810 提供的信息。试图将它实现到我的代码中,我没有得到任何结果,只是一个空的 var。不过还是感谢你发布这个算法,我会在接下来的几天里尝试修复它。
猜你喜欢
  • 2012-05-20
  • 1970-01-01
  • 1970-01-01
  • 2014-12-08
  • 1970-01-01
  • 2013-10-19
相关资源
最近更新 更多