用c语言编写素数

时间:2015-12-24 17:05:14

标签: c multithreading unix sieve-of-eratosthenes

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

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

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

#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);
    }
}

2 个答案:

答案 0 :(得分:2)

您正在尝试混合使用两种不同的方法来查找素数。您不需要使用迭代划分方法 Eratosthenes的筛子。这显示了实施筛子的方法。在筛子中忽略了偶数,但在isprime()中将其视为特殊情况。但是它不会帮助你找到一个多线程解决方案,因为你不能只是将不同的数字交给不同的线程 - 每个主要建立在前一个素数的工作上,从假设{{1是素数。

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;
}

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

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

节目输出:

// 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;
}

上述两个例子在处理大数字时都有一些陷阱,但我会让它们让你发现。

答案 1 :(得分:0)

这是 Eratosthenes Sieve 的修改版本,这是非常简单,有趣和快速的。理解它的工作,因为我试图用注释来解释它。实际上尝试理解数组大小的运行时分配,以避免定义大的MAX值,并尝试通过分析算法并应用好的数学和智能编码知识来编写简单的代码。

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int main()
{
    int *arr;
    int count=0,i=3,j,n;
    arr=(int*)malloc(count+1*sizeof(int)); //set array size to 1
    arr[count++]=2; //stored 2 as array first element
    printf("Find all prime numbers upto :: ");
    scanf("%d",&n); //n is the number up to which prime numbers are required
    here:
    {
        while(i<=n) //start with i=3
        {
            j=0;
            while(arr[j]<=sqrt(i)) //till array element value is less than or equal to root of number under checking
            {
                if(i%arr[j]!=0) //if remainder is not zero check divisibility with next array element
                    j++;              
                else
                {
                    i++;          //if remainder is zero then start checking for another number
                    goto here;
                }
        }
        printf("%d, ",arr[count-1]); //printing the number which was proved as prime last time
        arr=(int *)realloc(arr,(count+1)*sizeof(int)); //increasing array size by 1
        arr[count++]=i; //newly proved prime is stored as next array element
        i++;
    }
    printf("%d, ",arr[count-1]); //print last number proved as prime
}