繁体   English   中英

寻找素数的程序

[英]Program to find prime numbers

我想找到 0 和 long 变量之间的质数,但我无法获得任何输出。

该程序是

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

任何人都可以帮我找出程序中可能存在的错误吗?

您可以在一条(长)行中使用近乎最佳的试验分割筛来更快地完成此操作,如下所示:

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)的素数进行测试。

请注意, Eratosthenes筛选具有比试除法更好的运行时间复杂度(如果正确实施,对于更大的num值应该运行得更快)。

试试这个:

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

您只需要检查奇数除数直到数字的平方根。 换句话说,您的内部循环需要启动:

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

您也可以在发现数字不是质数时立即跳出该函数,您无需再检查除数(我知道您已经在这样做了!)。

这仅在 num 大于 2 时才有效。

无平方

您可以通过保持运行总和来完全避免 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小于ij小于平方根。

人们已经提到了有效地做到这一点的几个组成部分,但没有人真正将这些部分放在一起。 Eratosthenes筛子是一个好的开始,但是使用它你会在达到你设置的限制之前很久就耗尽内存。 但这并不意味着它没用——当你在做你的循环时,你真正关心的是质数除数。 因此,您可以首先使用筛选器创建素数除数的基数,然后使用循环中的那些来测试数字的素数。

然而,当你编写循环时,你真的不希望我们在循环条件中使用 sqrt(i) ,正如一些答案所建议的那样。 你我都知道 sqrt 是一个“纯”函数,如果给定相同的输入参数,它总是给出相同的答案。 不幸的是,编译器不知道这一点,所以如果在循环条件中使用类似 '<=Math.sqrt(x)' 的东西,它会在循环的每次迭代中重新计算数字的 sqrt。

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

这对于您正在处理的数字的大小来说可能已经足够了——15 位限制意味着平方根是 7 或 8 位,这适合相当合理的内存量。 另一方面,如果您想大量处理这个范围内的数字,您可能需要查看一些更复杂的素数检查算法,例如Pollard 或 Brent 算法 这些更复杂(委婉地说),但对于大数字来说快得多。

对于更大的数字,还有其他算法(二次筛一般数域筛),但我们暂时不会讨论它们——它们要复杂得多,而且实际上只对处理非常大的数字有用( GNFS 开始在 100+ 位范围内有用)。

第一步:写一个扩展方法来判断一个输入是否是素数

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

EDIT_ADD:如果 Will Ness 是正确的,那么这个问题的目的只是在程序运行期间输出连续的素数流(按暂停/中断暂停,按任意键重新开始),没有认真的希望那个上限,那么代码应该写成没有上限参数和第一个“i”循环的“真”范围检查。 另一方面,如果问题想要实际打印质数达到极限,那么以下代码将仅对奇数使用 Trial Division 更有效地完成这项工作,其优点是它根本不使用内存(它也可以转换为如上所述的连续循环):

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

首先,问题代码不产生任何输出,因为它的循环变量是整数,并且测试的限制是一个巨大的长整数,这意味着循环不可能达到产生内循环的限制编辑:变量'j'循环回到负数; 当 'j' 变量回到 -1 时,被测试的数字无法通过质数测试,因为所有数字都可以被 -1 END_EDIT整除。 即使这一点得到纠正,问题代码也会产生非常慢的输出,因为它会被限制在对非常大量的复合数(所有偶数加上奇数复合数)进行 64 位除法,直到那个顶部的整个数字范围对于它可能产生的每个素数,10 的 16 次方数。 上面的代码之所以有效,是因为它将计算限制为仅奇数,并且仅对当前被测试数的平方根进行模除。

这需要一个小时左右才能显示 10 亿以内的质数,因此可以想象将所有质数显示为 10000 万亿(10 的 16 次方)所需的时间,尤其是当计算变慢时随着范围的增加。 END_EDIT_ADD

尽管@SLaks 使用 Linq 给出的一个(某种)答案有效,但它并不是真正的 Eratosthenes 筛法,因为它只是Trial Division的未优化版本,未优化的原因在于它没有消除奇数素数,没有开始在找到的基本素数的平方处,并且不会停止剔除大于要筛选的顶部数字的平方根的基本素数。 由于多个嵌套的枚举操作,它也很慢。

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

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 实现运行速度快了大约 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; } }

上面的代码在英特尔 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++ 和非常高度优化的 PrimeSieve ,这将需要超过 400 个小时才能产生找到的素数数量,并且需要数十倍的时间来枚举所有这些素数,因此一年多来做问题所要求的。 要使用未优化的 Trial Division 算法来做到这一点,即使使用优化的 Trial Division 算法也需要花费超长的时间和非常长的时间,例如 10 到 200 万次幂年(即 200 万个零年!! !)。

难怪他的台式机在他尝试的时候就停滞不前了!!!! 如果他尝试了一个更小的范围,比如一百万,他仍然会发现它在实施时需要几秒钟的时间。

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

这就是为什么只有像 PrimeSieve 这样的页面分段方法才能完全处理指定范围内的此类问题,即使这样也需要很长的时间,如数周到数年,除非人们可以访问具有以下功能的超级计算机数十万个内核。 END_EDIT_ADD

这可能只是我的意见,但您的程序中存在另一个严重错误(搁置已彻底回答的给定“质数”问题)。

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

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

您的方法 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() );
    }
}

即使你最终在不需要这样的分散的地方工作,知道如何去做也是很好的。

闻起来像更多的家庭作业。 我非常非常古老的图形计算器有一个像这样的主要程序。 从技术上讲,内部设备检查循环只需要运行到 i^(1/2)。 您是否需要在 0 和 L 之间找到“所有”质数? 另一个主要问题是您的循环变量是“int”,而您的输入数据是“long”,这将导致溢出,使您的循环甚至无法执行一次。 修复循环变量。

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()));                                    

上面的 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))))是种子被清除的次数。

所以这基本上只是两个错别字,一个是最不幸的, 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分段筛 这是增量和无限的。

这两种方案都将使用双阶段生产素数:一个将生成并保存素数,以供另一阶段用于测试(或筛分),远高于第一阶段的限制(当然低于其平方 - 自动延长第一阶段,因为第二阶段会越来越远)。

ExchangeCore 论坛列出了一个很好的控制台应用程序,可以将找到的素数写入文件,看起来您也可以使用相同的文件作为起点,因此您不必重新从 2 开始查找素数,并且它们提供了该文件包含所有已找到的质数,最多 1 亿个,因此这将是一个好的开始。

页面上的算法还采用了一些快捷方式(奇数,只检查平方根),这使得它非常有效,并且可以让您计算长数。

坦率地说,一些建议的解决方案真的很慢,因此是不好的建议。 为了测试单个数字为素数,您需要一些除法/模运算符,但为了计算范围,您不必这样做。

基本上,您只需排除是较早发现的素数倍数的数字,因为它们(根据定义)不是素数本身。

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

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 分钟。

我知道这是一个安静的老问题,但在这里阅读后: 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 的索引。

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

非常相似 - 来自在 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;
    }
}

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

这是在 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");
        }
    }

此解决方案显示 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 + " "); }
        }
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);}

        }
    }

}

有一些非常优化的方法来实现该算法。 但是,如果您对数学不太了解,并且您只是遵循素数的定义作为要求:一个只能被 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 开始检查,直到它之前的数字。 这就是基本的推理。

你也可以这样做:

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

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

    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
    }

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

解决方案:

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"));

        }
    }

在大学里要数到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;
}

for (int i = 2; i < 100; i++) { bool isPrimeNumber = true; for (int j = 2; j <= i && j <= 100; j++) { if (i != j && i % j == 0) { isPrimeNumber = false; 休息; } } if (isPrimeNumber) { Console.WriteLine(i); } }

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

    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM