寻找素数的程序

时间:2009-10-02 15:07:20

标签: c# .net primes sieve-of-eratosthenes

我想找到介于0和长变量之间的素数,但我无法获得任何输出。

该计划

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication16
{
    class Program
    {
        void prime_num(long num)
        {
            bool isPrime = true;
            for (int i = 0; i <= num; i++)
            {
                for (int j = 2; j <= num; j++)
                {
                    if (i != j && i % j == 0)
                    {
                        isPrime = false;
                        break;
                    }
                }
                if (isPrime)
                {
                    Console.WriteLine ( "Prime:" + i );
                }
                isPrime = true;
            }
        }

        static void Main(string[] args)
        {
            Program p = new Program();
            p.prime_num (999999999999999L);
            Console.ReadLine();
        }
    }
}

任何人都可以帮助我,找出程序中可能出现的错误吗?

27 个答案:

答案 0 :(得分:74)

您可以使用近乎最佳的试验分区筛在一条(长)线上更快地完成此操作:

Enumerable.Range(0, Math.Floor(2.52*Math.Sqrt(num)/Math.Log(num))).Aggregate(
    Enumerable.Range(2, num-1).ToList(), 
    (result, index) => { 
        var bp = result[index]; var sqr = bp * bp;
        result.RemoveAll(i => i >= sqr && i % bp == 0); 
        return result; 
    }
);

此处使用的素数的近似公式为π(x) < 1.26 x / ln(x)。我们只需要通过不超过 x = sqrt(num) 的素数进行测试。

请注意,sieve of Eratosthenes的运行时间复杂度要比试用版更好(对于较大的 num 值,如果正确实施,则应该运行得更快。)

答案 1 :(得分:25)

试试这个:

void prime_num(long num)
{

    // bool isPrime = true;
    for (long i = 0; i <= num; i++)
    {
        bool isPrime = true; // Move initialization to here
        for (long j = 2; j < i; j++) // you actually only need to check up to sqrt(i)
        {
            if (i % j == 0) // you don't need the first condition
            {
                isPrime = false;
                break;
            }
        }
        if (isPrime)
        {
            Console.WriteLine ( "Prime:" + i );
        }
        // isPrime = true;
    }
}

答案 2 :(得分:9)

你只需要检查奇数除数,直到数字的平方根。换句话说,你的内循环需要开始:

for (int j = 3; j <= Math.Sqrt(i); j+=2) { ... }

一旦你发现数字不是素数,你也可以打破这个功能,你不需要再检查任何除数(我看你已经这样做了!)。

只有当num大于2时才会有效。

没有Sqrt

您可以通过保持运行总和来完全避免Sqrt。例如:

int square_sum=1;
for (int j=3; square_sum<i; square_sum+=4*(j++-1)) {...}

这是因为数字1+(3 + 5)+(7 + 9)的总和将给出一系列奇数正方形(1,9,25等)。因此j代表square_sum的平方根。只要square_sum小于i,则j小于平方根。

答案 3 :(得分:9)

人们已经提到了一些有效实现这一目标的构建模块,但没有人真正把这些部分放在一起。 sieve of Eratosthenes是一个很好的开始,但是在你达到你设定的限制之前,你将会耗尽内存 long 。这并不意味着它没用 - 当你做循环时,你真正关心的是主要的除数。因此,您可以首先使用筛子来创建素数除数的基数,然后使用循环中的那些来测试数字的首要性。

然而,当你编写循环时,你真的不希望我们在循环条件中使用sqrt(i),因为有几个答案已经提出。您和我知道sqrt是一个“纯”函数,如果给出相同的输入参数,它总是给出相同的答案。不幸的是,编译器不知道这一点,因此如果在循环条件中使用类似'&lt; = Math.sqrt(x)'的东西,它将在循环的每次迭代中重新计算数字的sqrt。

你可以通过几种不同的方式避免这种情况。您可以在循环之前预先计算sqrt,在循环条件中使用预先计算的值,也可以在另一个方向上工作,并将i<Math.sqrt(x)更改为i*i<x。就个人而言,我预先计算了平方根 - 我认为它更清晰,可能更快一点 - 但这取决于循环的迭代次数(i*i意味着它仍在进行乘法运算循环)。只需几次迭代,i*i通常会更快。通过足够的迭代,每次迭代i*i的丢失超过了循环外执行sqrt的时间。

这可能足以满足您正在处理的数字大小 - 15位数限制意味着平方根为7或8位数,这适合相当合理的内存量。另一方面,如果您想要处理此范围内的数字,您可能需要查看一些更复杂的质数检查算法,例如Pollard's or Brent's algorithms。这些更复杂(温和地说)但对于大数字来说,很多更快。

对于更大的数字(quadratic sievegeneral number field sieve)还有其他算法,但我们暂时不会进入它们 - 它们要复杂得多,而且实际上只对处理非常大的数字(GNFS在100多位数范围内开始有用)。

答案 4 :(得分:7)

第一步:编写扩展方法以确定输入是否为素数

public static bool isPrime(this int number ) {

    for (int i = 2; i < number; i++) { 
        if (number % i == 0) { 
            return false; 
        } 
    }

    return true;   
}

2步:编写将打印介于0和数字输入之间的所有素数的方法

public static void getAllPrimes(int number)
{
    for (int i = 0; i < number; i++)
    {
        if (i.isPrime()) Console.WriteLine(i);
    }
}

答案 5 :(得分:6)

EDIT_ADD:如果Will Ness是正确的,问题的目的只是在程序运行时输出连续的素数流(按暂停/中断暂停和任何重新开始的关键)没有严重希望每个达到上限,那么代码应该写成没有上限参数和范围检查&#34;真&#34;对于第一个&#39; i&#39; for循环。另一方面,如果问题想要实际打印质数达到一个限制,那么下面的代码将更有效地使用试验分区对奇数进行工作,其优点是它不会使用内存完全(它也可以按照上面的方式转换为连续循环):

static void primesttt(ulong top_number) {
  Console.WriteLine("Prime:  2");
  for (var i = 3UL; i <= top_number; i += 2) {
    var isPrime = true;
    for (uint j = 3u, lim = (uint)Math.Sqrt((double)i); j <= lim; j += 2) {
      if (i % j == 0)  {
        isPrime = false;
        break;
      }
    }
    if (isPrime) Console.WriteLine("Prime:  {0} ", i);
  }
}

首先,问题代码不产生输出,因为它的循环变量是整数,并且测试的极限是一个巨大的长整数,这意味着循环不可能达到产生内循环的极限 EDITED: 其中变量&#39; j&#39;循环回到负数;当&#39; j&#39;变量返回到-1,测试数字未通过主要测试,因为所有数字均可被-1 END_EDIT 整除。即使这被纠正了,问题代码也会产生非常慢的输出,因为它会被大量复合数字(所有偶数加上奇数复合数)的64位除以整个数字范围直到顶部对于它可能产生的每个素数,十个幂增加到十六个幂。上面的代码是有效的,因为它将计算限制为仅奇数,并且模数除以当前正在测试的数字的平方根

这需要一个小时左右来显示高达十亿的素数,所以可以想象将所有素数显示到一万亿(10提升到十六次幂)所需的时间量,尤其是计算随着范围的增加而变慢。的 END_EDIT_ADD

尽管@SLaks使用Linq的单线(某种)答案起作用,但它并不是Eratosthenes的Sieve,因为它只是Trial Division的未经优化的版本,未被优化,因为它没有消除奇素数,不在找到的基本素数的平方上开始,并且不会剔除大于顶部数字的平方根的基本素数进行筛选。由于多个嵌套的枚举操作,它也很慢。

实际上滥用Linq Aggregate方法并没有有效地使用生成的两个Linq Range中的第一个。它可以成为一个优化的试验部门,具有较少的枚举开销,如下所示:

static IEnumerable<int> primes(uint top_number) {
  var cullbf = Enumerable.Range(2, (int)top_number).ToList();
  for (int i = 0; i < cullbf.Count; i++) {
    var bp = cullbf[i]; var sqr = bp * bp; if (sqr > top_number) break;
    cullbf.RemoveAll(c => c >= sqr && c % bp == 0);
  } return cullbf; }

运行速度比SLaks的速度快很多倍。但是,由于List生成和多个枚举以及多重除法(模数隐含)操作,它仍然很慢并且内存密集。

以下真正的Eratosthenes实现的Sieve运行速度提高了大约30倍并且占用的内存要少得多,因为它只对每个筛选的数字使用一位表示并将其枚举限制为最终的迭代器序列输出,并且只有处理的优化奇数复合,只从基本素数的平方中剔除基本素数到最大数的平方根,如下所示:

static IEnumerable<uint> primes(uint top_number) {
  if (top_number < 2u) yield break;
  yield return 2u; if (top_number < 3u) yield break;
  var BFLMT = (top_number - 3u) / 2u;
  var SQRTLMT = ((uint)(Math.Sqrt((double)top_number)) - 3u) / 2u;
  var buf = new BitArray((int)BFLMT + 1,true);
  for (var i = 0u; i <= BFLMT; ++i) if (buf[(int)i]) {
      var p = 3u + i + i; if (i <= SQRTLMT) {
        for (var j = (p * p - 3u) / 2u; j <= BFLMT; j += p)
          buf[(int)j] = false; } yield return p; } }

以上代码在Intel i7-2700K(3.5 GHz)上计算出大约77毫秒内所有素数到千万范围。

可以使用using语句和静态Main方法调用和测试两个静态方法中的任何一个,如下所示:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

static void Main(string[] args) {
  Console.WriteLine("This program generates prime sequences.\r\n");

  var n = 10000000u;

  var elpsd = -DateTime.Now.Ticks;

  var count = 0; var lastp = 0u;
  foreach (var p in primes(n)) { if (p > n) break; ++count; lastp = (uint)p; }

  elpsd += DateTime.Now.Ticks;
  Console.WriteLine(
    "{0} primes found <= {1}; the last one is {2} in {3} milliseconds.",
    count, n, lastp,elpsd / 10000);

  Console.Write("\r\nPress any key to exit:");
  Console.ReadKey(true);
  Console.WriteLine();
}

将显示序列中的素数数量达到极限,找到最后一个素数,以及计算那么远的时间。

EDIT_ADD:但是,为了产生一个小于万万(十到十六次幂)的素数的枚举问题,使用多核的分段分页方法处理是必需的,但即使使用C ++和very highly optimized PrimeSieve,这也需要超过400小时才能产生所发现的素数,并且需要数十倍的长时间才能枚举所有这些素数以便在一年之内完成问题问。要使用未经优化的试验分区算法进行尝试,即使使用优化的试验分区算法也需要超长时间和非常长的时间,例如在十亿到二百万电力年(即百万分之二百万年)零年代!!!)。

当他尝试使用台式机时,他的台式机只是坐着并且停滞不动!如果他尝试过较小的范围,例如一百万,那么他仍然会发现实施的时间范围为秒。

我在这里发布的解决方案不会削减它,因为即使是最后一个Eratosthenes的Sieve也需要大约640TB的内存。

这就是为什么只有像PrimeSieve那样的页面分段方法才能处理指定范围内的这类问题,甚至需要很长时间,如几周到几年,除非有人可以访问拥有数十万个核心的超级计算机。的 END_EDIT_ADD

答案 6 :(得分:6)

这可能只是我的意见,但是你的程序中还有另一个严重的错误(撇开给定的'素数'问题,这个问题已得到彻底解答)。

与其他响应者一样,我假设这是家庭作业,这表明你想成为一名开发人员(大概)。

您需要学习划分代码。这不是你在项目中总是需要做的事情,但知道如何去做是件好事。

您的方法prime_num(long num)可以代表更好,更具描述性的名称。如果它应该找到小于给定数字的所有素数,它应该将它们作为列表返回。这样可以更容易地分离您的显示器和功能。

如果它只是返回一个包含素数的IList,那么你可以在主函数中显示它们(也许可以调用另一个外部函数来打印它们),或者在进一步的计算中使用它们。

所以我最好的建议是做这样的事情:

public void main(string args[])
{
    //Get the number you want to use as input
    long x = number;//'number' can be hard coded or retrieved from ReadLine() or from the given arguments

    IList<long> primes = FindSmallerPrimes(number);

    DisplayPrimes(primes);
}

public IList<long> FindSmallerPrimes(long largestNumber)
{
    List<long> returnList = new List<long>();
    //Find the primes, using a method as described by another answer, add them to returnList
    return returnList;
}

public void DisplayPrimes(IList<long> primes)
{
    foreach(long l in primes)
    {
        Console.WriteLine ( "Prime:" + l.ToString() );
    }
}

即使你最终在某个不需要这种拼版的地方工作,也不知道怎么做。

答案 7 :(得分:5)

闻起来更多的功课。我非常古老的图形计算器有一个像这样的主要程序。技术上,内部划分检查循环只需要运行到i ^(1/2)。你需要找到0到L之间的“全部”素数吗?另一个主要问题是你的循环变量是“int”,而你的输入数据是“长”,这将导致溢出使你的循环甚至一次都无法执行。修复循环变量。

答案 8 :(得分:2)

C#中的一行代码: -

Console.WriteLine(String.Join(Environment.NewLine, 
    Enumerable.Range(2, 300)
        .Where(n => Enumerable.Range(2, (int)Math.Sqrt(n) - 1)
        .All(nn => n % nn != 0)).ToArray()));                                    

答案 9 :(得分:2)

上面的Sieve of Eratosthenes答案不太正确。如上所述,它将找到介于1和1000000之间的所有素数。要查找1和num之间的所有素数:

private static IEnumerable Primes01(int num)
{
    return Enumerable.Range(1, Convert.ToInt32(Math.Floor(Math.Sqrt(num))))
        .Aggregate(Enumerable.Range(1, num).ToList(),
        (result, index) =>
            {
                result.RemoveAll(i => i > result[index] && i%result[index] == 0);
                return result;
            }
        );
}

Aggregate的种子应该是1到num的范围,因为这个列表将包含最终的素数列表。 Enumerable.Range(1, Convert.ToInt32(Math.Floor(Math.Sqrt(num))))是种子被清除的次数。

答案 10 :(得分:1)

所以这基本上只是两个错别字,一个是最不幸的,for (int j = 2; j <= num; j++)这是1%2,1%3 ... 1%(10^15-1)非生产性测试的原因,持续了很长时间所以OP没有得到“任何输出”应该j < i;代替。另一个是次要的,i应该从2开始,而不是从0开始:

for( i=2; i <= num; i++ )
{
    for( j=2; j < i; j++ ) // j <= sqrt(i) is really enough
....

当然,在任何合理的时间范围内完成28万亿次素数的控制台打印输出是不合理的。因此,问题的最初意图显然是打印出稳定的素数流,无限期。因此,所有提出简单使用Eratosthenes筛的解决方案在这里完全没有价值,因为Eratosthenes的简单筛是有限的 - 必须提前设定限制。

这里可以使用的是优化的试验分区,它可以在找到它们时保存素数,并测试素数,而不仅仅是候选者下面的所有数字。

第二种选择,具有更好的复杂性(即更快)是使用segmented sieve of Eratosthenes。这是增量和无限的。

这两个方案都会使用质数的双阶段生产:一个会产生并保存质数,供测试(或筛分)中的另一个阶段使用,远远高于极限第一阶段(当然低于其平方 - 自动延伸第一阶段,因为第二阶段会越走越远)。

答案 11 :(得分:1)

ExchangeCore Forums列出了一个很好的控制台应用程序,它可以将找到的素数写入文件,看起来你也可以使用同一个文件作为起点,这样你就不必重新开始从2找到质数并且他们提供了该文件的下载,其中所有已发现的素数高达1亿,因此这将是一个良好的开端。

页面上的算法也需要几个快捷方式(奇数并且只检查平方根),这使得它非常有效,并且它允许你计算长数。

答案 12 :(得分:1)

坦率地说,一些建议的解决方案确实很慢,因此是不好的建议。要测试单个数字是素数,你需要一些除法/模运算符,但是用于计算你不需要的范围。

基本上你只是排除那些早先找到的素数的倍数,因为它们(按照定义)不是素数本身。

我不会给出完整的实现,因为这很容易,这是伪代码中的方法。 (在我的机器上,实际实现在8秒内计算Sytem.Int32(2 bilion)中的所有素数。

public IEnumerable<long> GetPrimes(long max)
{
    // we safe the result set in an array of bytes.
    var buffer = new byte[long >> 4];
    // 1 is not a prime.
    buffer[0] = 1;

    var iMax = (long)Math.Sqrt(max);

    for(long i = 3; i <= iMax; i +=2 )
    {
        // find the index in the buffer
        var index = i >> 4;
        // find the bit of the buffer.
        var bit = (i >> 1) & 7;

        // A not set bit means: prime
        if((buffer[index] & (1 << bit)) == 0)
        {
            var step = i << 2;
            while(step < max)
            {
                // find position in the buffer to write bits that represent number that are not prime.
            }
        }
        // 2 is not in the buffer.
        yield return 2;

        // loop through buffer and yield return odd primes too.
    }
}

解决方案需要很好地理解按位运算。但它的方式和方式更快。如果您需要它们以供以后使用,您也可以保证光盘上结果的结果。 17 * 10 ^ 9个数字的结果可以用1 GB进行保护,并且该结果集的计算最多需要2分钟。

答案 13 :(得分:1)

我知道这是一个安静的老问题,但在阅读之后: Sieve of Eratosthenes Wiki

这是我通过理解算法编写它的方式:

void SieveOfEratosthenes(int n)
{
    bool[] primes = new bool[n + 1];

    for (int i = 0; i < n; i++)
        primes[i] = true;

    for (int i = 2; i * i <= n; i++)
        if (primes[i])
            for (int j = i * 2; j <= n; j += i)
                primes[j] = false;

    for (int i = 2; i <= n; i++)
        if (primes[i]) Console.Write(i + " ");
}

在第一个循环中,我们用true填充布尔数组。

第二个for循环将从2开始,因为1不是素数,并将检查质数是否仍未更改,然后将false指定给j的索引。

最后一个循环,我们只是在它是素数时打印。

答案 14 :(得分:0)

在大学里要数到10000的质数才这样做,老师有点惊讶,但我还是通过了考试。朗c#

void Main()
{
    int number=1;
    for(long i=2;i<10000;i++)
    {
        if(PrimeTest(i))
        {
            Console.WriteLine(number+++" " +i);
        }
    }
}

List<long> KnownPrime = new List<long>();
private bool PrimeTest(long i)
{
    if (i == 1) return false;
    if (i == 2)
    {
        KnownPrime.Add(i);
        return true;
    }
    foreach(int k in KnownPrime)
    {
        if(i%k==0)
            return false;
    }
    KnownPrime.Add(i);
    return true;
}

答案 15 :(得分:0)

static void Main(string[] args)
    {  int i,j;
        Console.WriteLine("prime no between 1 to 100");
    for (i = 2; i <= 100; i++)
    {
        int count = 0;
        for (j = 1; j <= i; j++)
        {

            if (i % j == 0)
            { count=count+1; }
        }

        if ( count <= 2)
        { Console.WriteLine(i); }


    }
    Console.ReadKey();

    }

答案 16 :(得分:0)

这是带有单元测试的解决方案:

解决方案:

public class PrimeNumbersKata
    {
        public int CountPrimeNumbers(int n)
        {
            if (n < 0) throw new ArgumentException("Not valide numbre");
            if (n == 0 || n == 1) return 0;
            int cpt = 0;
            for (int i = 2; i <= n; i++)
            {
                if (IsPrimaire(i)) cpt++;
            }
            return cpt;
        }

        private bool IsPrimaire(int number)
        {

            for (int i = 2; i <= number / 2; i++)
            {
                if (number % i == 0) return false;
            }
            return true;
        }
    }

测试:

[TestFixture]
    class PrimeNumbersKataTest
    {
        private PrimeNumbersKata primeNumbersKata;
        [SetUp]
        public void Init()
        {
            primeNumbersKata = new PrimeNumbersKata();
        }
        [TestCase(1,0)]
        [TestCase(0,0)]
        [TestCase(2,1)]
        [TestCase(3,2)]
        [TestCase(5,3)]
        [TestCase(7,4)]
        [TestCase(9,4)]
        [TestCase(11,5)]
        [TestCase(13,6)]
        public void CountPrimeNumbers_N_AsArgument_returnCountPrimes(int n, int expected)
        {
            //arrange
            //act
            var actual = primeNumbersKata.CountPrimeNumbers(n);
            //assert
            Assert.AreEqual(expected,actual);
        }

        [Test]
        public void CountPrimairs_N_IsNegative_RaiseAnException()
        {
            var ex = Assert.Throws<ArgumentException>(()=> { primeNumbersKata.CountPrimeNumbers(-1); });
            //Assert.That(ex.Message == "Not valide numbre");
             Assert.That(ex.Message, Is.EqualTo("Not valide numbre"));

        }
    }

答案 17 :(得分:0)

一种更简单的方法,我所做的就是检查一个数是否恰好有两个除数,这就是质数的本质。

    List<int> factorList = new List<int>();
    int[] numArray = new int[] { 1, 0, 6, 9, 7, 5, 3, 6, 0, 8, 1 };

    foreach (int item in numArray)
    {

        for (int x = 1; x <= item; x++)
        {
          //check for the remainder after dividing for each number less that number
            if (item % x == 0)
            {
                factorList.Add(x);
            }
        }
        if (factorList.Count == 2) // has only 2 division factors ; prime number
        {
            Console.WriteLine(item + " is a prime number ");
        }
        else
        {Console.WriteLine(item + " is not a prime number ");}

        factorList = new List<int>(); // reinitialize list
    }

答案 18 :(得分:0)

您也可以这样做:

class Program
  {
    static void Main(string[] args)
    {
      long numberToTest = 350124;
      bool isPrime = NumberIsPrime(numberToTest);
      Console.WriteLine(string.Format("Number {0} is prime? {1}", numberToTest, isPrime));
      Console.ReadLine();
    }

    private static bool NumberIsPrime(long n)
    {
      bool retVal = true;

      if (n <= 3)
      {
        retVal = n > 1;
      } else if (n % 2 == 0 || n % 3 == 0)
      {
        retVal = false;
      }

      int i = 5;

      while (i * i <= n)
      {
        if (n % i == 0 || n % (i + 2) == 0)
        {
          retVal = false;
        }
        i += 6;
      }

      return retVal;
    }
  }

答案 19 :(得分:0)

有一些非常优化的方法可以实现该算法。但是,如果您对数学不是很了解,只需遵循素数的定义作为要求: 一个只能被1和本身(以及其他所有东西)整除的数字,这是一个易于理解的正数代码。

public bool IsPrime(int candidateNumber)
{
    int fromNumber = 2;
    int toNumber = candidateNumber - 1;

    while(fromNumber <= toNumber)
    {
        bool isDivisible = candidateNumber % fromNumber == 0;
        if (isDivisible)
        {
            return false;
        }

        fromNumber++;
    }
    return true;
}

由于每个数字都可以被1本身除以整数,因此我们从2开始进行检查,直到紧邻其本身的数字为止。这是基本的推理。

答案 20 :(得分:0)

class CheckIfPrime
   {
    static void Main()
      {
          while (true)
        {
            Console.Write("Enter a number: ");
            decimal a = decimal.Parse(Console.ReadLine());
            decimal[] k = new decimal[int.Parse(a.ToString())];
            decimal p = 0;
            for (int i = 2; i < a; i++)
            {
                if (a % i != 0)
                {
                    p += i;
                    k[i] = i;
                }
                else
                    p += i;
            }
            if (p == k.Sum())
               { Console.WriteLine ("{0} is prime!", a);}
            else
               {Console.WriteLine("{0} is NOT prime", a);}

        }
    }

}

答案 21 :(得分:0)

此解决方案显示0到100之间的所有素数。

        int counter = 0;
        for (int c = 0; c <= 100; c++)
        {
            counter = 0;
            for (int i = 1; i <= c; i++)
            {
                if (c % i == 0)
                { counter++; }
            }
            if (counter == 2)
            { Console.Write(c + " "); }
        }

答案 22 :(得分:0)

这是在C#中计算素数的最快方法。

   void PrimeNumber(long number)
    {
        bool IsprimeNumber = true;
        long  value = Convert.ToInt32(Math.Sqrt(number));
        if (number % 2 == 0)
        {
            IsprimeNumber = false;
        }
        for (long i = 3; i <= value; i=i+2)
        {             
           if (number % i == 0)
            {

               // MessageBox.Show("It is divisible by" + i);
                IsprimeNumber = false;
                break;
            }

        }
        if (IsprimeNumber)
        {
            MessageBox.Show("Yes Prime Number");
        }
        else
        {
            MessageBox.Show("No It is not a Prime NUmber");
        }
    }

答案 23 :(得分:0)

非常相似 - 从练习到在C#中实施Eratosthenes筛选:

public class PrimeFinder
{
    readonly List<long> _primes = new List<long>();

    public PrimeFinder(long seed)
    {
        CalcPrimes(seed);
    }

    public List<long> Primes { get { return _primes; } }

    private void CalcPrimes(long maxValue)
    {
        for (int checkValue = 3; checkValue <= maxValue; checkValue += 2)
        {
            if (IsPrime(checkValue))
            {
                _primes.Add(checkValue);
            }
        }
    }

    private bool IsPrime(long checkValue)
    {
        bool isPrime = true;

        foreach (long prime in _primes)
        {
            if ((checkValue % prime) == 0 && prime <= Math.Sqrt(checkValue))
            {
                isPrime = false;
                break;
            }
        }
        return isPrime;
    }
}

答案 24 :(得分:0)

U可以使用正常素数概念必须只有两个因子(一个和它自己)。 所以这样做,简单方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PrimeNUmber
{
    class Program
    {
        static void FindPrimeNumber(long num)
        {
            for (long i = 1; i <= num; i++)
            {
                int totalFactors = 0;
                for (int j = 1; j <= i; j++)
                {
                    if (i % j == 0)
                    {
                        totalFactors = totalFactors + 1;
                    }
                }
                if (totalFactors == 2)
                {
                    Console.WriteLine(i);
                }
            }
        }

        static void Main(string[] args)
        {
            long num;
            Console.WriteLine("Enter any value");
            num = Convert.ToInt64(Console.ReadLine());
            FindPrimeNumber(num);
            Console.ReadLine();
        }
    }
}

答案 25 :(得分:0)

Prime Helper非常快速的计算

public static class PrimeHelper
{

    public static IEnumerable<Int32> FindPrimes(Int32 maxNumber)
    {
        return (new PrimesInt32(maxNumber));
    }

    public static IEnumerable<Int32> FindPrimes(Int32 minNumber, Int32 maxNumber)
    {
        return FindPrimes(maxNumber).Where(pn => pn >= minNumber);
    }

    public static bool IsPrime(this Int64 number)
    {
        if (number < 2)
            return false;
        else if (number < 4 )
            return true;

        var limit = (Int32)System.Math.Sqrt(number) + 1;
        var foundPrimes = new PrimesInt32(limit);

        return !foundPrimes.IsDivisible(number);
    }

    public static bool IsPrime(this Int32 number)
    {
        return IsPrime(Convert.ToInt64(number));
    }

    public static bool IsPrime(this Int16 number)
    {
        return IsPrime(Convert.ToInt64(number));
    }

    public static bool IsPrime(this byte number)
    {
        return IsPrime(Convert.ToInt64(number));
    }
}

public class PrimesInt32 : IEnumerable<Int32>
{
    private Int32 limit;
    private BitArray numbers;

    public PrimesInt32(Int32 limit)
    {
        if (limit < 2)
            throw new Exception("Prime numbers not found.");

        startTime = DateTime.Now;
        calculateTime = startTime - startTime;
        this.limit = limit;
        try { findPrimes(); } catch{/*Overflows or Out of Memory*/}

        calculateTime = DateTime.Now - startTime;
    }

    private void findPrimes()
    {
        /*
        The Sieve Algorithm
        http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
        */
        numbers = new BitArray(limit, true);
        for (Int32 i = 2; i < limit; i++)
            if (numbers[i])
                for (Int32 j = i * 2; j < limit; j += i)
                     numbers[j] = false;
    }

    public IEnumerator<Int32> GetEnumerator()
    {
        for (Int32 i = 2; i < 3; i++)
            if (numbers[i])
                yield return i;
        if (limit > 2)
            for (Int32 i = 3; i < limit; i += 2)
                if (numbers[i])
                    yield return i;
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    // Extended for Int64
    public bool IsDivisible(Int64 number)
    {
        var sqrt = System.Math.Sqrt(number);
        foreach (var prime in this)
        {
            if (prime > sqrt)
                break;
            if (number % prime == 0)
            {
                DivisibleBy = prime;
                return true;
            }
        }
        return false;
    }

    private static DateTime startTime;
    private static TimeSpan calculateTime;
    public static TimeSpan CalculateTime { get { return calculateTime; } }
    public Int32 DivisibleBy { get; set; }
}

答案 26 :(得分:0)

    public static void Main()
    {  
        Console.WriteLine("enter the number");
        int i = int.Parse(Console.ReadLine());

        for (int j = 2; j <= i; j++)
        {
            for (int k = 2; k <= i; k++)
            {
                if (j == k)
                {
                    Console.WriteLine("{0}is prime", j);

                    break;
                }
                else if (j % k == 0)
                {
                    break;
                }
            }
        }
        Console.ReadLine();          
    }