【问题标题】:Prime or not Prime output slow [duplicate]Prime 与否 Prime 输出缓慢 [重复]
【发布时间】:2019-04-08 13:00:08
【问题描述】:

这是 C 程序。这是我下面的code。我在终端中使用了nano。当我使用./a.out 9872349901 进行编译和测试时,我花了整整一分钟才得到结果……有人知道为什么它很慢吗? (我相信它可能是太长的数字,但我使用int isprime(long long n) {这是我的 CS 课程,当我做 labcheck 时,它是自动分配等级来获得分数,但它不会显示我的,因为 labcheck 不会等待它。

/**
 * Make a function called isprime that returns true (i.e. 1) if the integer
 * number passed to it is prime and false (i.e. 0) if it is composite (i.e.
 * not prime.)  A number is composite if it is divisible by 2 or any odd number
 * up to the square root of the number itself, otherwise it is prime.
 * Hint: n is divisible by m if (n % m == 0)
 */

/**
 * Using the isprime function you made above, test if a number provided on the
 * command line is prime or not. The program should print a usage message if no
 * number is provided ("Usage: p4 <number>\n") and print a warning if the number
 * is less than 2 ("input number should be > 1\n") and should be able to handle
 * numbers greater than 4 billion.
 * 
 * Example input/output:
 * ./p4 9872349901
 * 9872349901 is prime
 * ./p4 65
 * 65 is not prime
 */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>

int isprime(long long n) {
    for (long long i = 2; i != n; ++i)
        if (n%i == 0)
            return 0;
    return 1;
}

int main (int argc, char *argv[])
{
    if (argc < 2)
    {
        printf ("Usage: p4 <number>\n");
        return -1;
    }
    char* p;
    long long n = strtoll(argv[1], &p, 10);
    if (n < 2 || *p != '\0')
    {
        printf ("input wrong\n");
        return -1;
    }
    int result = isprime(n);

    if (result == 1)
        printf ("%lld is prime\n", n);
    else
        printf ("%lld is not prime\n", n);
    return 0;
}

许多不同的数字都可以完美运行,但不适用于 9872349901,因为这是教师测试我作业的数字。

这是我做“实验室检查”时的预览

cs25681@cs:/instructor/class/cs25681/cs/h5> labcheck 5
Checking assignment #5:
p1:
p2:
p3:
p4:
-3.0 output of program (p4) is not correct for input '9872349901':
------ Yours: ------
---- Reference: ----
9872349901 is prime
--------------------
p5:
p6:
p7:
p8:

我想为每个不同的数字测试它,所以这里是./a.out &lt;number&gt;的预览

cs25681@cs:/lecture/class/cs25681/cs> ./a.out 3
3 is prime
cs25681@cs:/lecture/class/cs25681/cs> ./a.out 1
input wrong
cs25681@cs:/lecture/class/cs25681/cs> ./a.out 9
9 is not prime
cs25681@cs:/lecture/class/cs25681/cs> ./a.out 9872349901
9872349901 is prime
cs25681@cs:/lecture/class/cs25681/cs> echo "took 43 seconds to output"
took 43 seconds to output
cs25681@cs:/lecture/class/cs25681/cs> 

【问题讨论】:

  • 不用查[2..n][2..sqrt(n)]就够了。你应该检查维基百科en.wikipedia.org/wiki/Prime_number#Computational_methods
  • 它甚至在标题注释中的说明中说,您应该只测试到 sqrt(n)。
  • 我应该把 sqrt(n) 放在哪里?我认为我之前在任何 c 程序中都没有使用 sqrt(n)。
  • 使用for (long long i = 2; i * i &lt;= n; ++i)。更好的算法将测试 2,然后测试 3、5、7,...;更好的是,测试 2 和 3,然后测试 6*N±1,N = 1, 2, 3, ... 测试 5, 7, 11, 13, 17, 19, 23, 25(这是第一次不是' t 选择素数对)等。注意不要使用sqrt(N);你使用i * i &lt;= N。或者,如果必须使用sqrt(N),则计算循环前的值并使用计算值。向上舍入到下一个整数。
  • 足够的理论,在实践中,它很慢,因为检查是否找到一个素数通常很慢。使超过一分钟的数字变得相当快的唯一方法是并行化(您可以购买一个特殊的 CPU,该 CPU 设计时考虑了并行算法,或者只是使用 OpenGL 之类的东西并在您的 GPU 上执行一些巫毒着色器魔法使用帧缓冲区(1 像素 = X 可被 Y 整除(如何获得这些是另一个问题)并在片段着色器中写入白色或黑色或其他内容),或者如果你有一个好的 GPU,则可以使用计算着色器) .

标签: c integer primes slowdown


【解决方案1】:

将我的评论转化为答案。

用途:

for (long long i = 2; i * i <= n; ++i)

这会限制测试,直到 i 刚好大于 n 的平方根,如代码注释中所建议的那样。

更好的算法会先测试 2,然后再测试奇数 3、5、7,...,这样可以大大减少测试量。

更好的是,测试 2 和 3,然后测试 6*N±1,N = 1, 2, 3, ... 测试 5, 7, 11, 13, 17, 19, 23, 25(这是第一次它没有选择素数对)等。

if (n <= 1)
    return 0;
if (n == 2 || n == 3)
    return 1;
if (n % 2 == 0 || n % 3 == 0)
    return 0;
for (unsigned long long x = 5; x * x <= n; x += 6)
{
    if (n % x == 0 || n % (x + 2) == 0)
        return 0;
}
return 1;

注意不要使用sqrt(N);你使用i * i &lt;= N。或者,如果必须使用sqrt(N),则计算循环前的值并使用计算值,向上舍入到下一个整数(ceil() 来自&lt;math.h&gt;)。至少,这是我几年前的基准测试告诉我的。

JFTR:将上面的代码转移到问题中的代码中,并且计时 p4 9872349901 产生的报告表明它在大约 0.005 秒的经过时间内是主要的(在具有 2.7 GHz Intel Core 的普通 2016 15" MacBook Pro 上i7 处理器)。我还尝试了 98723499017333(在数字的右端添加 4 位数字,并在点击这个之前获得一些非质数),它在 0.044 秒内报告为质数。非质数报告当然更快。

【讨论】:

  • 其中一些代码在我的SOQ(堆栈溢出问题)存储库中作为isprime.c 文件在 GitHub 上的Primes 子目录中提供。
猜你喜欢
  • 2018-07-23
  • 1970-01-01
  • 2021-07-19
  • 2015-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多