龙空技术网

26.人工智能:大数分解——分别采用单线性、多线程、多进程实现

UNET 234

前言:

当前看官们对“pollard p算法”大概比较注重,看官们都想要了解一些“pollard p算法”的相关知识。那么小编也在网摘上收集了一些对于“pollard p算法””的相关资讯,希望同学们能喜欢,小伙伴们一起来了解一下吧!

一、什么是大数分解

给一个大数n,将它分解成质因子的乘积的形式。比如:

49716575159173590222=3*3*2*3*19*37199*73331*17763763

大数分解最简单的思想也是试除法,就是从2到sqrt(n),一个一个的试验,直到除到1或者循环完,最后判断一下是否已经除到1了即可。但这样效率很低,需要使用其他算法来实现大数分解。

大数应该至少要在20位以上的整数,因为超过20位以上的整数,用普通的试除法就很难分解。

二、大数分解算法:

1、Miller-Rabin 素性检测算法

Miller-Rabin算法本质上是一种概率算法,存在误判的可能性,但是出错的概率非常小。出错的概率到底是多少,存在严格的理论推导。

MillerRabbin素性测试算法涉及到二个定理:

### 1.1、费马小定理

如果p为质数:a^(p-1)≡ 1 (mod p)

注意,p是质数,一定满足费马小定理,但是,满足费马小定理的数,并不能证明就是质数。

### 1.2、二次探测定理

对于任意一个小于p的正整数x,发现1(mod p)的非平凡平方根存在,则说明p是合数。

如果p是一个素数,0 < x< p, 则方程 x^2 ≡ 1(mod p) 的解为 x=1 ,x= p-1。

反之如果 x^ 2 ≡ 1(mod p) 的解不是 x=1 ,x= p-1 那 p 就不是素数

2、Pollard-rho算法

由于普通的试除法进行大数分解,复杂度是相当高的。一种很妙的思路是找到一个因子(不一定是质因子),然后再一路分解下去。

这就是基于Miller_rabin的大数分解法Pollard_rho大数分解。Pollard_rho算法的大致流程是 先判断当前数是否是素数(Miller_rabin)了,如果是则直接返回。

如果不是素数的话,试图找到当前数的一个因子(可以不是质因子)。然后递归对该因子和约去这个因子的另一个因子进行分解。

二、单线性——实现大数分解

实现代码

import sysfrom random import randintfrom math import gcdimport timesys.setrecursionlimit(100000)import threadingdef isPrime(n,t=50):           t = min(n-3,t)    if n <2:                return    if n==2: return True    s = n-1    r = 0        #分解成2^r*s形式     while s%2==0:        r=r+1        s=s//2    tested=set()    #出错概率1/2^t     for i in range(t):        a = randint(2,n-2)        while a in tested:#不取重复随机数a            a = randint(2,n-2)        tested.add(a)                x= pow(a,s,n)        if x==1 or x==n-1:            continue  #继续返回测试                #二次探测        for j in range(r):            x= x*x % n            if x==1 or x==n-1:break #继续返回测试        else:            return False #合数    return Truedef factor(n):        #递归出口    if n==1: return     if isPrime(n):        #print(n)        return [n]    #初始化:因子,环数,x1,x2由x1决定    p=1    loop=2    x1 = randint(1, n-1)    x2 = x1    #随机取一个常数c,用来构造x1,x1=x1*x1+c    c = randint(1,n)    #循环直到找到n的质因子p    while p==1:                    for i in range(loop):            #如果找到一个因子,则退出            if p>1:break                        x1=(x1*x1+c)%n             #如果x1=x2,则重新选择x1                       if x1==x2:                c = randint(1,n)                continue            p = gcd(x1-x2,n) #如果p>1刚找到n的一个质因子p        loop=loop *2 #环数加倍        x2 = x1    #如果找到n的一个质因子p,则递归继续            return factor(p)+factor(n//p)n=int(input("n:"))print(n,len(str(n)))start_time=time.time()print(factor(n))print('运行时间:', time.time()-start_time)

运行结果:

n:123456123456123456123456

123456123456123456123456 24

[3, 2, 2, 2, 2, 2, 2, 101, 137, 73, 643, 9901, 99990001]

运行时间: 0.003989696502685547

单线性——演示视频:

视频加载中...

三、多线程——实现大数分解

import sysfrom random import randintfrom math import gcdimport timeimport threadingdef isPrime(n,t=50):           t = min(n-3,t)    if n <2:                return    if n==2: return True    s = n-1    r = 0        #分解成2^r*s形式     while s%2==0:        r=r+1        s=s//2    tested=set()    #出错概率1/2^t     for i in range(t):        a = randint(2,n-2)        while a in tested:#不取重复随机数a            a = randint(2,n-2)        tested.add(a)                x= pow(a,s,n)        if x==1 or x==n-1:            continue  #继续返回测试                #二次探测        for j in range(r):            x= x*x % n            if x==1 or x==n-1:break #继续返回测试        else:            return False #合数    return Truelst=[] #全局变量使用t_list=[] #线程列表def factor(n):        #print('当前线程的名字是: ', threading.current_thread().name)          #递归出口    if n==1: return     if isPrime(n):        #print(n,",")        lst.append(n) #全局变量存放结果        return n    #初始化:因子,环数,x1,x2由x1决定    p=1    loop=2    x1 = randint(1, n-1)    x2 = x1    #随机取一个常数c,用来构造x1,x1=x1*x1+c    c = randint(1,n)    #循环直到找到n的质因子p    while p==1:                    for i in range(loop):            #如果找到一个因子,则退出            if p>1:break                        x1=(x1*x1+c)%n             #如果x1=x2,则重新选择x1                       if x1==x2:                c = randint(1,n)                continue            p = gcd(x1-x2,n) #如果p>1刚找到n的一个质因子p        loop=loop *2 #环数加倍        x2 = x1    #如果找到n的一个质因子p,则递归继续             t1=threading.Thread(target=factor,args=(p,))    t2=threading.Thread(target=factor,args=(n//p,))    t_list.append(t1)    t_list.append(t2)    t1.start()    t2.start()    #return t1,t2n=int(input("n:"))start_time=time.time()factor(n)for t in t_list:    t.join()print("运行结果:",lst)print('运行时间:', time.time()-start_time)###############验证分解后的值s=1for i in lst:    s=s*iprint("n:",s,s==n)

运行结果:

n:123456123456123456123456

运行结果: [2, 2, 3, 2, 2, 2, 101, 2, 73, 137, 643, 9901, 99990001]

运行时间: 0.0071179866790771484

多线程——演示视频:

视频加载中...

四、多进程——实现大数分解

import sysfrom random import randintfrom math import gcdimport timeimport multiprocessingdef isPrime(n,t=50):           t = min(n-3,t)    if n <2:                return    if n==2: return True    s = n-1    r = 0        #分解成2^r*s形式     while s%2==0:        r=r+1        s=s//2    tested=set()    #出错概率1/2^t     for i in range(t):        a = randint(2,n-2)        while a in tested:#不取重复随机数a            a = randint(2,n-2)        tested.add(a)                x= pow(a,s,n)        if x==1 or x==n-1:            continue  #继续返回测试                #二次探测        for j in range(r):            x= x*x % n            if x==1 or x==n-1:break #继续返回测试        else:            return False #合数    return Truep_list=[]def factor(n,lst):        #print(multiprocessing.current_process(),multiprocessing.current_process().pid)           #递归出口    if n==1: return     if isPrime(n):        #print(n,",")        lst.append(n) #全局变量存放结果        return n    #初始化:因子,环数,x1,x2由x1决定    p=1    loop=2    x1 = randint(1, n-1)    x2 = x1    #随机取一个常数c,用来构造x1,x1=x1*x1+c    c = randint(1,n)    #循环直到找到n的质因子p    while p==1:                    for i in range(loop):            #如果找到一个因子,则退出            if p>1:break                        x1=(x1*x1+c)%n             #如果x1=x2,则重新选择x1                       if x1==x2:                c = randint(1,n)                continue            p = gcd(x1-x2,n) #如果p>1刚找到n的一个质因子p        loop=loop *2 #环数加倍        x2 = x1    p1=multiprocessing.Process(target=factor,args=(p,lst))              p2=multiprocessing.Process(target=factor,args=(n//p,lst))       p_list.append(p1)    p_list.append(p2)    p1.start()    p2.start()    return p1,p2def pmain(__name__, p_list, factor):    if __name__ =='__main__':        n=int(input("n:"))        lst= multiprocessing.Manager().list()        #定义进程共享列表变量        start_time=time.time()        factor(n,lst)        for p in p_list:            p.join()        print("运行结果:",lst)        print('运行时间:', time.time()-start_time)        ##############验证分解后的值        s=1        for i in lst:            s=s*i        print("n:",s,s==n)pmain(__name__, p_list, factor)

运行结果:

n:123456123456123456123456

运行结果: [2, 2, 3, 2, 2, 2, 2, 137, 73, 101, 643, 9901, 99990001]

运行时间: 1.7835564613342285

多进程——演示视频:

视频加载中...

五、单线性、多线程、多进程性能比较

通过下面一组数据比较,发现多线程在CPU密集型操作上,并没有的优势,多进程性能表现更优。

标签: #pollard p算法