c - C语言中的素数

标签 c multithreading unix sieve-of-eratosthenes

我想通过多线程和使用E.函数的Sieve来查找素数。我写了一些代码。如果程序将运行,用户输入最大数量和线程数量。程序应该创建给定线程号的线程。该程序找到所有素数,直到最大数。每个线程必须检查一个素数。

我的程序找不到素数。我编写了 checkPrime 函数和 crossout 函数来有效地查找素数。但这不起作用。所以,我无法检查我的线程是否正常工作。如何实现checkPrime功能?

有3个功能。划线用于 Sieve E. 方法。 checkPrime 用于检查数字是否为质数。 worker是线程的功能。每个线程必须检查一个质数。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>

#define MAX_N 100000000
#define MAX_THREADS 25

// global values
int threadNumber;
int largestNumber;
int isPrime;
int nthreads,  // number of threads (not counting main())
    prime[MAX_N + 1],
    n,  // in the end, prime[i] = 1 if i prime, else 0
    nextbase;  // next sieve multiplier to be used

// lock for the shared variable nextbase
pthread_mutex_t nextbaselock = PTHREAD_MUTEX_INITIALIZER;

void crossout(int a) {
    int i, j, check;
    for (i = 2; i < largestNumber; i++)
        prime[i] = 1;

    for (i = a; i < largestNumber;)
        if (prime[i])
            for (j = i; i * j < largestNumber; j++)
                prime[i * j] = 0;

}

int checkPrime(int a) {
    int i;
    for (i = 2; i <= a; ++i) {
        if (a % i == 0) {
            isPrime = 1;
            return isPrime;
            break;
        } else
            isPrime = 2;
        crossout(a);
        return isPrime;
    }
}

void*  workerThread(void* t) {

    int lim, base;

    long i, j;
    long tid;

    tid = (long)t;
    printf("Thread %ld starting...\n", tid);

    while (1)  {


        pthread_mutex_lock(&nextbaselock);
        base = nextbase;
        nextbase++;
        // unlock the lock
        pthread_mutex_unlock(&nextbaselock);
        if (base <= lim)  {

            if (prime[base])  {
                checkPrime(base);
                // log work done by this thread
            }
        }
        if (checkPrime(base) == 2)
            printf("Thread %ld done. Prime = %d\n", tid, base);
        pthread_exit((void*) t);
    }

    return NULL;
}

//main function with two parameters :argc and argv
int main(int argc, char** argv) {

    threadNumber = argv[3];
    largestNumber = argv[1];


    int i;

    pthread_t thread[threadNumber];
    int rc;
    long t;
    void* status;

    for (t = 0; t < threadNumber; t++) {
        printf("Main: creating thread %ld\n", t);
        rc = pthread_create(&thread[t], NULL, workerThread, (void*)t);
        if (rc) {
            printf("ERROR; return code from pthread_create() is %d\n", rc);
            exit(-1);
        }
    }

    for (t = 0; t < threadNumber; t++) {
        rc = pthread_join(thread[t], (void*)&t);
        if (rc) {
            printf("ERROR; return code from pthread_join() is %d\n", rc);
            exit(-1);
        }
        printf("Main: completed join with thread %ld \n", t);
    }
}

最佳答案

您正在尝试混合两种不同的方法来查找素数。您不需要同时使用迭代除法埃拉托色尼筛法。这显示了一种实现筛子的方法。偶数在筛子中会被忽略,但在 isprime() 中被视为特殊情况。但它不会帮助您找到多线程解决方案,因为您不能只是将不同的数字交给不同的线程 - 每个素数都建立在前一个素数的工作基础上,从假设 3 是质数。

// Sieve of Eratosthenes
#include <stdio.h>
#include <stdlib.h>

#define LIMIT   200

char sieve[LIMIT] = { 1, 1, };                  // 1 for not-prime

int isprime(unsigned n)
{
    if(n <= 2)                                  // special cases
        return sieve[n] == 0;
    if(n % 2 == 0)                              // even numbers are not prime
        return 0;
    if(n >= LIMIT)                              // test range
        exit(1);
    return sieve[n] == 0;
}

int main(void)
{
    unsigned n, p;
    for(n=3; n<LIMIT; n+=2) {                   // odd numbers only
        if (sieve[n] == 0) {                    // if n is prime
            for(p=n*n; p<LIMIT; p+=n*2) {       // ignore even numbers
                sieve[p] = 1;                   // not primne
            }
        }
    }

    printf("Prime numbers are:\n");
    for(n=0; n<LIMIT; n++) {                    // check all numbers
        if (isprime(n)) {                       // if n is prime
            printf("%-4d", n);
        }
    }
    printf("\n");
    return 0;
}

程序输出:

Prime numbers are:
2   3   5   7   11  13  17  19  23  29  31  37  41  43  47  53  59  61  67  71
73  79  83  89  97  101 103 107 109 113 127 131 137 139 149 151 157 163 167 173
179 181 191 193 197 199

我现在将展示一种迭代除法。偶数再次被视为特殊情况。我不经常编写多线程 C 代码,所以我无法帮助你。但我希望您可以在第二个示例的基础上构建多线程解决方案。

// iterative division
#include <stdio.h>
#include <math.h>

#define LIMIT   200

int isprime(unsigned n)
{
    unsigned s, i;
    if(n <= 1)
        return 0;
    if(n == 2)
        return 1;
    if(n % 2 == 0)                              // no even numbers
        return 0;
    s = (unsigned)sqrt(n);                      // limit the loop
    for(i=3; i<=s; i+=2)                        // odd numbers only
        if (n % i == 0)
            return 0;
    return 1;
    }

int main(void)
{
    unsigned n;
    printf("Prime numbers are:\n");
    for(n=0; n<LIMIT; n++) {                    // check all numbers
        if (isprime(n)) {                       // if n is prime
            printf("%-4d", n);
        }
    }
    printf("\n");
    return 0;
}

程序输出:

Prime numbers are:
2   3   5   7   11  13  17  19  23  29  31  37  41  43  47  53  59  61  67  71
73  79  83  89  97  101 103 107 109 113 127 131 137 139 149 151 157 163 167 173
179 181 191 193 197 199

在处理较大数字时,上述两个示例都存在一些陷阱,但我将把它们留给您去发现。

关于c - C语言中的素数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34455888/

相关文章:

c - 进程同步- TestAndSetLock

c - 如何在 Windows 文本编辑器上阻止打印功能(CTRL + P)?

c - 与进程树中的兄弟共享PID

Java - 在哪里检测和捕获 SocketException

java - 并发测试: test case scenario automatization

linux - 如果我截断到比原来更大的尺寸,ftruncate() 会复制数据吗?

相同函数的 C const/非常量版本

c - 编程查找二维数组中的相邻单元格

c++ - 如何使用 boost::asio::io_service 在 C++11 线程之间调度作业

linux - Unix awk 命令 BEGIN 和 END 语法错误