C# 求两个大数之间素数的有效算法

C# 求两个大数之间素数的有效算法,c#,algorithm,primes,C#,Algorithm,Primes,我是C#的初学者,我正试图编写一个应用程序来获取用户输入的两个数字之间的素数。问题是:在大数情况下(有效数在1到100000000之间),获取素数需要很长时间,根据我正在解决的问题,整个操作必须在很短的时间间隔内执行。这是问题链接以获取更多解释: 下面是我的代码中负责获取素数的部分: public void GetPrime() { int L1 = int.Parse(Limits[0]); int L2 = int.Par

我是C#的初学者,我正试图编写一个应用程序来获取用户输入的两个数字之间的素数。问题是:在大数情况下(有效数在1到100000000之间),获取素数需要很长时间,根据我正在解决的问题,整个操作必须在很短的时间间隔内执行。这是问题链接以获取更多解释:

下面是我的代码中负责获取素数的部分:

  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;
       }