C# 求两个大数之间素数的有效算法
我是C#的初学者,我正试图编写一个应用程序来获取用户输入的两个数字之间的素数。问题是:在大数情况下(有效数在1到100000000之间),获取素数需要很长时间,根据我正在解决的问题,整个操作必须在很短的时间间隔内执行。这是问题链接以获取更多解释: 下面是我的代码中负责获取素数的部分:C# 求两个大数之间素数的有效算法,c#,algorithm,primes,C#,Algorithm,Primes,我是C#的初学者,我正试图编写一个应用程序来获取用户输入的两个数字之间的素数。问题是:在大数情况下(有效数在1到100000000之间),获取素数需要很长时间,根据我正在解决的问题,整个操作必须在很短的时间间隔内执行。这是问题链接以获取更多解释: 下面是我的代码中负责获取素数的部分: public void GetPrime() { int L1 = int.Parse(Limits[0]); int L2 = int.Par
public void GetPrime()
{
int L1 = int.Parse(Limits[0]);
int L2 = int.Parse(Limits[1]);
if (L1 == 1)
{
L1++;
}
for (int i = L1; i <= L2; i++)
{
for (int k = L1; k <= L2; k++)
{
if (i == k)
{
continue;
}
else if (i % k == 0)
{
flag = false;
break;
}
else
{
flag = true;
}
}
if (flag)
{
Console.WriteLine(i);
}
}
}
public void GetPrime()
{
int L1=int.Parse(限制[0]);
int L2=int.Parse(限制[1]);
如果(L1==1)
{
L1++;
}
对于(int i=L1;i你正在做很多不需要的额外除法-如果你知道一个数字不能被3整除,那么检查它是否可以被9、27等整除是没有意义的。你应该尝试只被这个数字的潜在素数因子除法。缓存你正在生成的素数集,只检查被前一个p除法请注意,您确实需要生成L1以下的初始素数集
请记住,没有一个数的素数因子大于其自身的平方根,因此您可以在该点停止除法。例如,您可以在5之后停止检查数字29的潜在因子
也可以增加2,这样就可以忽略检查偶数是否为素数(当然,特殊情况下是数字2)
我曾经在采访中问过这个问题——作为一个测试,我将一个类似于你的实现与我描述的算法进行了比较。使用优化的算法,我可以非常快地生成数十万个素数——我从来没有费心等待缓慢、直接的实现。你可以尝试不同的是,可以从L1
开始,而不是从2
开始。有许多算法可以找到素数。有些算法更快,有些更容易
您可以从进行一些最简单的优化开始。例如
- 为什么要搜索每个数字是否都是素数?换句话说,如果给定411到418的范围,是否需要搜索数字412、414、416和418是否是素数?可以通过非常简单的代码修改跳过除以2和3的数字
- 如果数字不是5,而是以数字“5”(1405335)结尾,这不是一个坏主意:它会使搜索速度变慢
- 缓存结果怎么样?然后你可以除以素数,而不是除以每个数。此外,只考虑小于搜索数平方根的素数
如果您需要快速且优化的解决方案,可以选择使用现有算法,而不是重新发明轮子。您也可以尝试找到一些科学论文,解释如何快速实现,但这可能很难理解,也很难转化为代码。我记得解决过这样的问题:
for(k=ceil(m/p)*p; k <= n; k += p) status[k-m] = 0;
使用生成数组primes
中低于sqrt(100000000)=~32000
的所有素数
对于m
和n
之间的每个数字x
,仅通过测试其与数字的可分性来测试其是否为素数让我们稍微改变一下问题:您能以多快的速度生成m和n之间的素数,并将它们简单地写入内存?(或者,可能写入RAM磁盘)另一方面,请记住问题页面上描述的参数范围:m和n可以高达10亿,而n-m最多为100万
IVlad和Brian是最具竞争力的解决方案,即使较慢的解决方案确实足够好。首先生成甚至预计算小于sqrt(十亿)的素数;数量不多。然后对Eratosthenes进行截断筛选:制作一个长度为n-m+1的数组,以跟踪[m,n]范围内每个数字的状态,最初每个数字都标记为素数(1)。然后对每个预计算的素数p执行如下循环:
for(k=ceil(m/p)*p; k <= n; k += p) status[k-m] = 0;
for(k=ceil(m/p)*p;k没有人提到的一件事是测试单个数字的素性。因此,如果涉及的范围很小,但数字很大(例如,生成100000000到1000100000之间的所有素数),单独检查每个数字的素性会更快。int-ceilingNumber=1000000;
int ceilingNumber = 1000000;
int myPrimes = 0;
BitArray myNumbers = new BitArray(ceilingNumber, true);
for(int x = 2; x < ceilingNumber; x++)
if(myNumbers[x])
{
for(int y = x * 2; y < ceilingNumber; y += x)
myNumbers[y] = false;
}
for(int x = 2; x < ceilingNumber; x++)
if(myNumbers[x])
{
myPrimes++;
Console.Out.WriteLine(x);
}
Console.Out.WriteLine("======================================================");
Console.Out.WriteLine("There is/are {0} primes between 0 and {1} ",myPrimes,ceilingNumber);
Console.In.ReadLine();
int-myPrimes=0;
BitArray myNumbers=新的BitArray(ceilingNumber,true);
对于(int x=2;x
我认为我有一个非常快速有效的(生成所有素数,即使使用BigInteger类型)算法来获取素数,它比任何其他算法都要快得多,也更简单,我使用它来解决几乎与Project Euler中的素数相关的问题,只需几秒钟即可获得完整的解决方案(蛮力)
以下是java代码:
public boolean checkprime(int value){ //Using for loop if need to generate prime in a
int n, limit;
boolean isprime;
isprime = true;
limit = value / 2;
if(value == 1) isprime =false;
/*if(value >100)limit = value/10; // if 1 number is not prime it will generate
if(value >10000)limit = value/100; //at lest 2 factor (not 1 or itself)
if(value >90000)limit = value/300; // 1 greater than average 1 lower than average
if(value >1000000)limit = value/1000; //ex: 9997 =13*769 (average ~ sqrt(9997) is 100)
if(value >4000000)limit = value/2000; //so we just want to check divisor up to 100
if(value >9000000)limit = value/3000; // for prime ~10000
*/
limit = (int)Math.sqrt(value); //General case
for(n=2; n <= limit; n++){
if(value % n == 0 && value != 2){
isprime = false;
break;
}
}
return isprime;
}
public boolean checkprime(int值){//如果需要在
int n,极限;
布尔互质;
isprime=true;
极限=值/2;
如果(值==1)isprime=false;
/*如果(值>100)limit=value/10;//如果1个数字不是素数,它将生成
如果(值>10000)限制=值/100;//至少2个因素(不是1或自身)
如果(值>90000)限制=值/300;//1大于平均值1小于平均值
如果(值>1000000)limit=value/1000;//ex:9997=13*769(平均~sqrt(9997)为100)
我
List<int> prime(int x, int y)
{
List<int> a = new List<int>();
int b = 0;
for (int m = x; m < y; m++)
{
for (int i = 2; i <= m / 2; i++)
{
b = 0;
if (m % i == 0)
{
b = 1;
break;
}
}
if (b == 0) a.Add(m)`
}
return a;
}