【问题标题】:Efficient prime number function高效素数函数
【发布时间】:2013-10-26 15:27:28
【问题描述】:

所以我正在尝试创建一个函数,该函数将返回 1 或 0,具体取决于给定数字是否为质数。

注意:我确定给定的数字是自然的。大于 1

我原来的功能:

int Prime(int a) {
    int i;
    for (i = 2; i*i <= a; i++)
    {
       if ((a % i) == 0)
          return 0;
    };
    return 1;
}

工作得很好,但不知何故……慢。我正在寻找一种更有效的算法,而不使用数组。我的第二次尝试:

int Prime(int a) {
    int i;
    if (a == 2)
       return 1;
    if ((a % 2) == 0)
       return 0;

    for (i = 3; i*i <= a; i = i + 3)
    {
       if ((a % i) == 0) 
          return 0;
    };

    return 1;
}

结局很糟糕。有一些数字(我无法想象)小于MAX_INT,导致这个特定算法的工作非常缓慢。所以,我有两个问题:

  1. 我的升级算法有问题吗?

  2. 有没有什么方法可以更有效地完成这项任务?

【问题讨论】:

  • 您可能想在 sqrt(a) 处停下来。
  • 首先,您可能希望将i*i 存储在一个变量中,而不是为每次迭代计算它。
  • @Kunal 或者更确切地说用-O2 编译,它将由编译器完成。
  • 您应该将 i = i + 3 更改为 i = i + 2。您可以将前两个 if 语句组合为: if (a % 2 == 0) return a == 2;
  • 您可以对 2、7 和 61 运行 Miller-Rabin 测试:en.wikipedia.org/wiki/…

标签: c performance primes


【解决方案1】:

1) 我升级后的算法有问题吗?

是的。

i=i+3 必须是 i=i+2,否则您将检查 3 的倍数 (3,6,9,12,...) 而不是奇数 (3,5,7,9,...) )

2) 有没有什么方法可以更有效地完成这项任务?

您可以计算 sqrt(a) 并将其分配给变量(例如 sqrtOfA),然后在循环条件中检查 i &lt;= sqrtOfA

或者你可以试试prime number sieve,比如sieve of Eratosthenes

【讨论】:

  • 感谢您的回复。那 i=i+3 只是我的错误,算法中有 i=i+2 。但问题仍然存在。就筛子而言,我无法找到一种方法来让它们在没有数组的情况下发生。我对数组的问题在于它的大小。即使数字很大,我也需要这个算法来工作
  • @MichalKučera 请记住,使用筛子,每个数字都可以是一个位,因此最多可以在 256 MB 中存储 2147483647。如果不是这样,我认为您将无法获得更高效的 (guaranteed) 素数检查器。
  • 所以,我现在尝试在这个函数中实现一个筛子。我有基本的想法,但还有一个问题。我需要创建尽可能大的数组,而且我的 RAM 非常有限。有没有数据类型,可以包含数字 1 和 0,并且尽可能的小?
  • 对于 C 语言?您可能必须自己创建这样的数据结构,虽然它并不太难,请参阅this question 了解更多信息(如果您实际使用 C++,则有 std::bitset)。
  • @MichalKučera - 我看到你刚刚开始使用 SO。如果此答案对您有所帮助,则单击或接受并不是一件坏事:)
【解决方案2】:

这取决于您是否想知道数字是素数还是仅具有高概率素数。 如果您对程序可能给出错误答案或流星崩溃而感到满意,而流星崩溃的可能性更大,那么您可以使用 O(1) 检查,如 Miller-Rabin 测试。

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

还有一个确定性 O(n^12) 算法用于素数测试,但在实践中使用不多。

【讨论】:

    【解决方案3】:

    @Dukeling 是绝对正确的。另外,我想添加一个小条件来检查“是 1 素数吗?”

    因为在标准过程中,在循环本身的帮助下,我们得到 1 不是素数。但是在这里,我们必须手动添加一个条件。

    所以只需添加以下 'if' 条件,您的代码就会完美运行!

    if(a==1)
    return 0;
    

    【讨论】:

      猜你喜欢
      • 2015-07-17
      • 2014-02-17
      • 2011-10-12
      • 2019-10-10
      • 2016-08-25
      • 2020-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多