如何生成用户定义的素数?

时间:2010-03-10 06:50:42

标签: c# primes

我正在尝试根据用户输入生成素数。这是我到目前为止所得到的,但我似乎无法弄明白:

Console.Write("Please enter the number of prime numbers you would like to see:");
int numberOfPrimes = Convert.ToInt32(Console.ReadLine());

for (int x = 0; x < numberOfPrimes; x++)
{
    for (int a = 2; a <= x ; ++a)
    {
        bool prime = true;
        for (int b = 2; b < a; ++b)
        {
            if (a % b == 0)
            {
                prime = false;
            }//end if
        }//end double nested for
        if (prime == true)
        {
            Console.WriteLine(a);
        }//end if
    }//end nested for
}//end for

7 个答案:

答案 0 :(得分:3)

如果你看一下你的循环结构,你应该能够很容易地看出你的结果错误的原因。手工完成它们(不会花很长时间)。

您获得当前结果的原因是外循环(x < numberOfPrimes)的每次迭代都不会产生结果 - 由于内部循环的结构方式,它将跳过相当多的迭代。 / p>

你真正需要做的是重构内循环。你最内层的循环工作正常,应该检测任何素数。但是,您的第二个循环应该只测试尚未测试的数字。此外,一旦找到素数,它应该停止循环。

答案 1 :(得分:1)

你应该更好地构建你的代码,它现在的方式非常麻烦。有一个方法IsPrime(int x)如果x为素数则返回true,否则返回false。

然后,要生成numberOfPrimes素数,您可以执行以下操作:

for ( int primeCount = 0, currentPrime = 2; primeCount < numberOfPrimes; ++currentPrime )
  if ( IsPrime(currentPrime) )
  {
    // do whatever you want with currentPrime, like print it
    ++primeCount;
  }

或者使用Sieve of Eratosthenes,这是一种更快的方法。

要确定某个号码x是否为素数,请尝试2Sqrt(x)之间的所有因素。为什么只有Sqrt(x)?因为如果是a*b = x,那么x / b = ax / a = b,那么你会检查所有内容两次,如果你去x / 2甚至{{ 1}}。

如果你想使用x函数,那就是这样:

IsPrime(x)

但我建议你使用Eratosthenes的筛子,因为它要快得多。你也可以优化一些东西,这样你就不会检查偶数,因为偶数是绝对的,除了2(在筛子和天真的方法中)。将x = 2视为边缘情况,然后开始检查每隔一个数字(3,5,7,9,11等)

答案 2 :(得分:0)

一旦你完成了循环整理,你只需要检查b&lt; sqrt(a),任何更高,你会先找到另一个因素。

答案 3 :(得分:0)

您正在寻找的是“Eratosthenes的筛子”。因为我不做人的作业,这是我要给你的唯一线索。该算法很容易在互联网上找到。

答案 4 :(得分:0)

下一个素数(x) - 是不能被所有素数s除的数,即s <= sqrt(x)。 所以你可以使用像

这样的功能
public bool CheckAndAddPrime(int number,List<int> primes)
{
    var sqrt = Math.Sqrt(number);
    foreach(var prime in primes)
    {
        if(prime>sqrt) break;
        if(number % prime == 0) return false;    
    }

    primes.Add(number);
    return true;
}

而且你可以获得像

这样的素数
var primes = new List<int>();
Enumerable.Range(2,int.MaxValue).Where(x => x.CheckAndAddPrime(x,primes)).Take(YouCountOfPrimes);

答案 5 :(得分:0)

var primes = Enumerable.Range(1, numberOfPrimes )
    .Where(x => x != 1 &&
      !Enumerable.Range2, (int)Math.Sqrt(x)).Any(y => x != y && x % y == 0));

copied from codethinked.com

static void Main(string[] args)
{
    foreach (int no in get_first_k_primes(10))
    {
        Console.Write(" "+no.ToString() );
    }
}

public static List<int> get_first_k_primes(int k)
{
    var primes = new List<int>();

    primes.Add(2);

    int i  = 3;


    while(primes.Count < k)
    {
        if(is_prime(i))
            primes.Add(i);

        i += 2;
    }

    return primes;
}

public static bool is_prime(int n)
{
    if (n % 2 == 0 && n != 2) return false;

    int m = (int)Math.Ceiling(Math.Sqrt(n));

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

    return true;
}

答案 6 :(得分:0)

<强> 1。重命名变量。

首先,如果这是作业,你会得到不好的分数(如果你的老师值得他的盐),因为你有无意义的变量名称(是的,即使numberOfPrimes是错误的,应该命名为requiredNumberOfPrimes。当我看到这个变量时,我会问自己'这是他想要多少,或者他找到了多少?')。

其次,它会帮助您了解出错的地方。变量应根据它们代表的内容进行逻辑命名。如果你无法解释你的变量代表什么(例如a&amp; b)那么你可能无法解释你在用它们做什么。

<强> 2。看看你的循环。

for (int x = 0; x < numberOfPrimes; x++)

for循环的结构是(initialise; 'should I continue?'; 'each loop do this')。因此在你的循环中

  • 您将继续,直到x等于或大于numberOfPrimes *。
  • 每次进行循环时,您都会向x添加1。

你确定这是你想做的吗? x似乎代表您找到的素数。那么为什么不在找到素数时增加它,而不是在开始循环时增加它?

for (int a = 2; a <= x ; ++a)
for (int b = 2; b < a; ++b)

您正在查看介于2和x之间的每个整数。对于每个整数a,您正在查看a和2之间的每个整数。你打算用这些整数做什么?

每次循环浏览顶级循环(x循环)时,您将从头开始a循环,每次循环遍历a循环,您将从头开始b循环。

因此,如果x为10,则运行一次(a = 2),然后再次运行a(a = 2,a = 3),然后再次运行a(a = 2) ,a = 3,a = 4),然后......

第3。收集结果而不是将其写入控制台。

var primes = new List<int>();

这很容易。当你找到素数时,primes.Add(a);。然后你知道你找到了多少素数(primes.Count),你可以使用素数列表来有效地确定下一个素数,如果需要你可以稍后使用该列表。