【问题标题】:Check if a number is prime in C# [duplicate]在C#中检查一个数字是否是素数[重复]
【发布时间】:2016-05-20 14:43:43
【问题描述】:

以下代码有效,但对于某些数字,它需要大量时间来判断该数字是否为质数。我该怎么做才能让它更快?代码如下:

using System;
using System.Collections.Generic;
using System.Linq;``
using System.Text;
using System.Threading.Tasks;

namespace Exercise23
{
    class Exercise23
    {
        static void Main(string[] args)
        {
            long number = long.Parse(Console.ReadLine());
            if (IsPrime(number))
            {
                Console.WriteLine("True");
            }
            else
            {
                Console.WriteLine("False");
            }
        }
        public static bool IsPrime(long number)
        {
            if (number == 1) return false;
            if (number == 2) return true;
            //if (number == 6737626471) return true;

            if (number % 2 == 0) return false;    

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

【问题讨论】:

  • 有些算法只需要很长时间,具体取决于输入,事实就是如此。想想那些计算 pi 的多位数仍然需要很多时间的超级计算机。
  • 这是确定素数最慢的算法之一。加快速度的第一步:您只需迭代到number 的平方根(更高的值不能是除数)。
  • @RenéVogt - 较高的值可以是除数 - 但如果有,您将已经找到至少一个其他除数(可以乘以较高的除数以获得原始数字)例如sqrt(10) 是 3.16。你会声称 5 不是 10 的除数吗?
  • @Damien_The_Unbeliever 没错,这就是我的意思 :)
  • 如果这段代码按原样工作,并且只是为了让它更快,它不属于 CodeReview 吗?

标签: c#


【解决方案1】:

最简单的改进是缩短循环。 如果数字不是素数,则可以写成

  N = A * B 

A &lt;= B;在最坏的情况下(A == B)和A &lt;= sqrt(N)

  public static bool IsPrime(long number) {
    if (number <= 1)
      return false;
    else if (number % 2 == 0)
      return number == 2;

    long N = (long) (Math.Sqrt(number) + 0.5);

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

    return true;
  }

所以你有O(sqrt(N)) 算法而不是O(N)。真正的改进(对于 big numbers)见

AKS 测试(主要用于学术)

https://en.wikipedia.org/wiki/AKS_primality_test

拉宾-米勒测试

https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test

【讨论】:

  • 这个可以写成for (int i = 3; i * i &lt;= number; i += 2),不用计算sqrt
  • @Phate01:从技术上讲,你是对的;但是sqrt 只计算了一次,而乘法在每次迭代时执行。
  • 我刚刚意识到性能问题:D
【解决方案2】:

基于这个答案:https://stackoverflow.com/a/26760082/4499267 加快速度的一种方法是:

  • 可以通过观察除 2 和 3 之外的所有素数的形式为 6k ± 1 来进一步改进算法。
  • 这是因为对于某个整数 k 和 i = -1、0、1、2、3 或 4,所有整数都可以表示为 (6k + i); 2 除 (6k + 0), (6k + 2), (6k + 4);和 3 个除法 (6k + 3)。
  • 因此更有效的方法是测试 n 是否可被 2 或 3 整除,然后检查 6k ± 1 ≤ √n 形式的所有数字。
  • 这是测试所有 m 到 √n 的速度的 3 倍。

这是一个 C 实现

int IsPrime(unsigned int number) {
    if (number <= 3 && number > 1) 
        return 1;            // as 2 and 3 are prime
    else if (number == 1 || number%2==0 || number%3==0) 
        return 0;     // check if number is divisible by 2 or 3
    else {
        unsigned int i;
        for (i=5; i*i<=number; i+=6) {
            if (number % i == 0 || number%(i + 2) == 0) 
                return 0;
        }
        return 1; 
    }
}

【讨论】:

    猜你喜欢
    • 2011-05-06
    • 2015-09-15
    • 2016-08-21
    • 1970-01-01
    • 2023-04-05
    • 2021-07-10
    • 2012-10-08
    • 2015-03-17
    相关资源
    最近更新 更多