【问题标题】:Checking for a prime number检查素数
【发布时间】:2013-01-01 11:42:19
【问题描述】:

我的任务有问题。如果数字是素数,我需要找到并提醒用户。

这是我的代码:

int a = Convert.ToInt32(number);

if (a % 2 !=0 )
{
    for (int i = 2; i <= a; i++)
    {
        if (a % i == 0)
        {
            Console.WriteLine("not prime");
        }
        else
        {
            Console.WriteLine("prime");
        }
        Console.WriteLine();
    }
}
else
{
    Console.WriteLine("not prime");
}
Console.ReadLine();

我哪里出错了,我该如何解决?

【问题讨论】:

  • for (int i = 3; i
  • 首先你需要了解什么是质数。 2是质数。你的第一个if-statement 另有说明。然后你应该检查每个已知 prime 的模数,而不是从 2 到数字的每个已知 number
  • 只需添加一个条件 i = a - 1 然后将其写为素数或非素数
  • 您也可以只检查数字的平方根。
  • @kovilpattiCsharper:代码还有很多问题。

标签: c# numbers primes


【解决方案1】:

素数可以被 1 整除,您需要检查数字是否正好有两个除数,从 1 到数字,然后它是素数。

 int devisors = 0;
 for (int i = 1; i <= a; i++)
     if (a % i == 0)                        
          devisors++;

 if (devisors == 2)                 
     Console.WriteLine("prime");
 else
     Console.WriteLine("not prime");

您可以跳过一次迭代,因为我们知道所有整数都可以被 1 整除,然后您将完全得到素数的除数。由于 1 只有一个除数,我们需要跳过它,因为它不是素数。所以条件是数字只有一个除数而不是 1,并且数字不应该是一,因为一不是素数。

 int devisors = 0;
 for (int i = 2; i <= a; i++)
     if (a % i == 0)                        
          devisors++;

 if (a != 1 && devisors == 1)                 
     Console.WriteLine("prime");
 else
     Console.WriteLine("not prime");

【讨论】:

  • 或者你跳过一个和那个数字并检查是否有任何除数。这允许循环在找到除数后立即停止。
【解决方案2】:

您只是打印素数或非素数,然后继续循环,而不是停止。 %2 检查并不是真正需要的。适当修改:

int a = Convert.ToInt32(number);

bool prime = true;
if (i == 1) prime = false;
for (int i = 2; prime && i < a; i++)
    if (a % i == 0) prime = false;
if (prime) Console.WriteLine("prime");
else Console.WriteLine("not prime");
Console.ReadLine();

【讨论】:

    【解决方案3】:
    public bool isPrime(int num)
    {
        for (int i = 2; i < num; i++)
            if (num % i == 0) 
                return false;                       
        return num == 1 ? false : true;
    }
    

    【讨论】:

      【解决方案4】:

      大概您的代码正在输出大量消息,这些消息看起来很混乱且毫无意义?有3个关键问题:

      • 当你决定它不能是质数时,你并没有打破你的 for 循环

      • 您假设它可能不是质数,请参阅下面代码中的 cmets。

      • 您正在与 a 本身进行比较,并且它始终可以被 a 整除,for 条件中的

      代码:

      int a = Convert.ToInt32(number);
      
      if (a % 2 != 0)
      {
          for (int i = 3 i < a; i += 2) // we can skip all the even numbers (minor optimization)
          {
              if (a % i == 0)
              {
                  Console.WriteLine("not prime");
                  goto escape; // we want to break out of this loop
              }
              // we know it isn't divisible by i or any primes smaller than i, but that doesn't mean it isn't divisible by something else bigger than i, so keep looping 
          }
          // checked ALL numbers, must be Prime
          Console.WriteLine("prime");
      }
      else
      {
          Console.WriteLine("not prime");
      }
      escape:
      Console.ReadLine();
      

      正如其他人提到的,您只能循环到 a 的平方根,通过每次评估平方根并替换此行:

      for (int i = 3 i < a; i += 2)
      

      用这个:

      float sqrRoot = (Int)Math.Sqrt((float)a);
      for (int i = 3 i <= sqrRoot; i += 2)
      

      对其进行评估很重要,否则您的程序将运行得更慢,而不是更快,因为每次迭代都涉及平方根运算。

      如果您不喜欢 goto 语句(我喜欢 goto 语句),请发表评论,我会将其替换为突破布尔值(或查看 Dukeling 的最新答案)。

      【讨论】:

      • goto 的问题是很难遵循所有的逻辑。有时它会使事情变得更容易,但在以后调试时,就很难看到事情的发展方向了。
      【解决方案5】:

      我做了太多素数检查。

      我这样做了:

      bool isPrime = true;
              List<ulong> primes = new List<ulong>();
              ulong nCheck, nCounted;
              nCounted = 0;
              nCheck = 3;
              primes.Add(2);
              for (; ; )
              {
                  isPrime = true;
                  foreach (ulong nModulo in primes)
                  {
                      if (((nCheck / 2) + 1) <= nModulo)
                      { break; }
                      if (nCheck % nModulo == 0)
                      { isPrime = false; }
                  }
                  if (isPrime == true)
                  {
                      Console.WriteLine("New prime found: " + (nCheck) + ", prime number " + (++nCounted) + ".");
                      primes.Add(nCheck);
                  }
                  nCheck++;
                  nCheck++;
              }
      

      虽然这不是您正在寻找的东西,所以我要做的是将它放在后台工作人员中,但将 ulongs 列表作为并发列表,或者您可以在 2 个线程中访问的东西。或者只是在访问列表时锁定列表。如果素数还没有计算出来,那就等到它完成。

      【讨论】:

        【解决方案6】:

        另一种优化方式是使用Sieve of Eratosthenes算法。

        来自Wikipedia

        用 Eratosthenes 的方法找出小于或等于给定整数 n 的所有素数:
        1. 创建一个从 2 到 n 的连续整数列表:(2, 3, 4, ..., n)。
        2. 最初,令 p 等于 2,即第一个素数。
        3. 从 p 开始,以 p 为增量向上计数,并在列表中标记每个大于 p 本身的数字。这些将是 p 的倍数:2p、3p、4p 等;请注意,其中一些可能已被标记。
        4. 找出列表中第一个大于 p 且未标记的数。如果没有这样的号码,请停止。否则,现在让 p 等于这个数(即下一个素数),然后从第 3 步开始重复。

        When the algorithm terminates, all the numbers in the list that are not marked are prime.
        

        C#代码

          int[] GetPrimes(int number) // input should be greater than 1
            {
                bool[] arr = new bool[number + 1];
                var listPrimes = new List<int>();
        
                for (int i = 2; i <= Math.Sqrt(number); i++)
                {
                    if (!arr[i])
                    {
                        int squareI = i * i;
                        for (int j = squareI; j <= number; j = j + i)
                        {
                            arr[j] = true;
                        }
                    }
        
                    for (int c = 1; c < number + 1; c++)
                    {
                        if (arr[c] == false)
                        {
                            listPrimes.Add(c);
                        }
                    }
        
                }
                return listPrimes.ToArray();
            }
        

        【讨论】:

        • 要检查一个给定的数字是否是素数,试除法要快得多。我不确定List 是如何实现的,但primeNumbers.Remove(toRemove); 看起来非常很可疑。如果这实际上从列表中删除了该数字,那么您将失去 O(1) 次随机访问,因此会变得更慢。
        • @DanielFischer 是的,RemoveContains 都是 O(n) 操作。
        • @Magnus 哎哟。所以它会是二次的,甚至比臭名昭著的特纳“筛子”还要糟糕。
        • 实现有问题。我会用更好的实现来更新它。但是随机访问模型的复杂性是O(nloglogn)。密钥是随机访问。随机访问本身可能是O(n)
        【解决方案7】:
            private static void checkpirme(int x)
            {
                for (int i = 1; i <= x; i++)
                {
                    if (i == 1 || x == i)
                    {
                        continue;
                    }
                    else
                    {
                        if (x % i == 0)
                        {
                            Console.WriteLine(x + " is not prime number");
                            return;
                        }
        
        
                    }
                }
                Console.WriteLine(x + " is  prime number");
            }
        

        其中 x 是检查它是否为素数的数字

        【讨论】:

          猜你喜欢
          • 2014-03-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-06-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多