Python 64位素数的最快因子(素数-1)/2?

Python 64位素数的最快因子(素数-1)/2?,python,c++,prime-factoring,factoring,Python,C++,Prime Factoring,Factoring,我试图收集一些关于素数的统计数据,其中包括(素数-1)/2的因子分布。我知道关于均匀选择数的因子大小有一些通用公式,但我没有看到任何关于小于素数1的因子分布的公式 我已经编写了一个程序,从2^63之后的第一个素数开始迭代素数,然后使用2^32之前的所有素数的除法计算(素数-1)/2的因子。然而,这是非常缓慢的,因为需要迭代大量的素数(和大量内存)。我将每个素数存储为一个字节(通过存储从一个素数到下一个素数的增量)。对于2^64以内的数字,我还使用了Miller-Rabin素性测试的一个确定性变体

我试图收集一些关于素数的统计数据,其中包括(素数-1)/2的因子分布。我知道关于均匀选择数的因子大小有一些通用公式,但我没有看到任何关于小于素数1的因子分布的公式

我已经编写了一个程序,从2^63之后的第一个素数开始迭代素数,然后使用2^32之前的所有素数的除法计算(素数-1)/2的因子。然而,这是非常缓慢的,因为需要迭代大量的素数(和大量内存)。我将每个素数存储为一个字节(通过存储从一个素数到下一个素数的增量)。对于2^64以内的数字,我还使用了Miller-Rabin素性测试的一个确定性变体,因此我可以很容易地检测出剩余值(成功除法后)是素数

我尝试过使用pollard rho和椭圆曲线分解的一种变体,但很难在尝试除法和切换到这些更复杂的方法之间找到正确的平衡。此外,我不确定我是否正确地实现了它们,因为有时它们似乎需要很长时间才能找到一个因子,并且基于它们的渐近行为,我希望它们对于如此小的数字会非常快

我还没有找到任何关于分解多个数字的信息(而不是仅仅尝试分解一个),但似乎应该有一些方法通过利用这一点来加速任务

任何关于这个问题的建议、替代方法的指针或其他指导都将不胜感激


编辑: 我存储素数的方法是存储到下一个素数的8位偏移量,隐式的第一个素数是3。因此,在我的算法中,我有一个单独的检查除以2,然后我开始一个循环:

factorCounts=collections.Counter()
当N%2==0时:
因子计数[2]+=1
N/=2
pp=3
对于smallPrimeGaps中的gg:
如果pp*pp>N:
打破
如果N%pp==0:
当N%pp==0时:
因子计数[pp]+=1
N/=pp
pp+=gg
此外,我还使用了一个轮筛来计算素数进行试除法,并使用了一种基于多个素数的余数的算法来获得给定起点后的下一个素数


我使用以下方法来测试给定的数字是否是Prime(现在将代码移植到C++):

bool IsPrime(uint64\n)
{
如果(n<341531)
返回MillerRabinMulti(n,{9345883071009581737ull});
否则,如果(n<1050535501)
返回MillerRabinMulti(n,{336781006125ull,9639812373923155ull});
否则如果(n<350269456337)
返回MillerRabinMulti(n,{42302792471168320ull,1469477155120705706ull,1664113952636775035ull});
否则如果(n<55245642489451)
返回MillerRabinMulti(n,{2ull,141889084524735ull,11991247256245411711096072698276303650});
否则如果(n<7999252175582851)
返回MillerRabinMulti(n,{2ull,4130806001517ull,14979543772692060ull,186635894390467037ull,3967304179347715805ull});
否则如果(n<585226005592931977)
返回MillerRabinMulti(n,{2ull,1236357097300ull,9233062284813009ull,43835965440333360ull,761179012939631437ull,1263739024124850375ull});
其他的
返回MillerRabinMulti(n,{2ull,325ull,9375ull,28178ull,450775ull,9780504ull,1795265022 ull});
}

这是我为以后存储素数的方式: (我假设你想要的是数字的因子,而不仅仅是素数测试)

从我的网站复制

我假设你知道这部分的二进制数系统。如果不是,就认为1是“是”,0是“否”

因此,有很多算法可以生成前几个素数。我用埃拉托什尼筛来计算一个列表

但是,如果我们将素数存储为数组,如[2,3,5,7],这将占用太多空间。到底有多少空间

32位整数可以存储2^32个字节,每个字节占用4个字节,因为每个字节是8位,32/8=4

如果我们想将每个素数存储在2000000000以下,我们必须存储9800000000以上。这会占用更多的空间,并且在运行时比位集慢,如下所述

这种方法需要98000000个整数空间(每个是32位,也就是4字节),当我们在运行时检查时,我们需要检查数组中的每个整数,直到找到它,或者找到一个大于它的数字

例如,假设我给你一个素数的小列表:[2,3,5,7,11,13,17,19]。我问你15是不是素数。你怎么告诉我的

好吧,你可以浏览一下列表,并将每个列表与15个进行比较

2等于15吗

3等于15吗

17等于15吗

在这一点上,你可以停下来,因为你已经通过了15的位置,所以你知道它不是素数

现在,让我们假设我们使用一个比特列表来告诉你这个数字是否是素数。上面的列表如下所示:

001101010001010001010

这从0开始,到19

1表示索引是素数,所以从左开始计数:0,1,2

001101010001010001010

最后一个粗体数字是1,表示2是素数

在这种情况下,如果我让你检查15是否为素数,你不需要遍历列表中的所有数字;你所需要做的就是跳到0。15,并检查单个位

对于内存使用,第一种方法使用98000000个整数,而这个方法可以在一个整数中存储32个数字(使用1和0的列表),因此我们需要 2000000000/32=62500000个整数

因此,它使用的内存大约是第一种方法的60%,而且使用速度更快

我们将第二种方法中的整数数组存储在一个文件中,然后在运行时将其读回

这使用250MB的ram来存储前2000000000个素数上的数据

你可以走得更远