C :: Aufgabe #70 :: Lösung #1

4 Lösungen Lösungen öffentlich
#70

Giuga-Zahlen berechnen

Anfänger - C von Gustl - 13.02.2015 um 12:42 Uhr
Eine natürliche Zahl n ist eine Giuga-Zahl, wenn alle ihre Primteiler p den Wert n/p - 1 teilen.

Schreibe ein Programm welches alle Giuga-Zahlen bis zu einer festen Obergrenze ausgibt.

Erläuterung zu einer Giuga-Zahl findest du hier: Wikipedia
#1
vote_ok
von devnull (8870 Punkte) - 01.03.2015 um 22:24 Uhr
Das Programm verwendet "unsigend int". Die 3- bis 5-faktorigen Giuga-Zahlen werden recht schnell berechnet, für größere Giuga-Zahlen ist der Faktorisier-Algorithmus (Probedivision) zu langsam.

Konsolenausgabe:


$ ./giuga_uint 1000000
Berechne Primzahlen bis 1000000...
78498 Primzahlen gefunden.
Suche Giuga-Zahlen bis 1000000
30 = 2*3*5
858 = 2*3*11*13
1722 = 2*3*7*41
66198 = 2*3*11*17*59

Quellcode ausblenden C-Code
/********************************************
 * giuga.c    Giuga-Zahlen berechnen
 ********************************************/
#include <stdlib.h>
#include <stdio.h>
 
#define MAX_SIEVE 1000000   // Array Limit Sieb
#define MAX_PRIME 100000    // Array Limit Primzahlen

unsigned char *psieve;
unsigned int *pprime, *ppfact;
int nsieve, nprime, npfact;

int alloc_buffers() {
	size_t bufsiz;
	
	// sieve buffer initialized with 0
	bufsiz = MAX_SIEVE / 8;
	if ((psieve = (unsigned char *)calloc(bufsiz,1)) == NULL) {
	  printf("Error sieve buffer allocation (%d byte)\n", (int)bufsiz);
	  return 1;
    }
	bufsiz = MAX_PRIME * sizeof(int);
	if ((pprime = (unsigned int *)malloc(bufsiz)) == NULL) {
	  printf("Error prime buffer allocation (%d byte)\n", (int)bufsiz);
	  return 1;
    }
	if ((ppfact = (unsigned int *)malloc(bufsiz)) == NULL) {
	  printf("Error factor buffer allocation (%d byte)\n", (int)bufsiz);
	  return 1;
    }
    return 0;
}

void free_buffers() {
	if (psieve != NULL) free(psieve);
	if (pprime != NULL)	free(pprime);
	if (ppfact != NULL)	free(ppfact);
}

void set_sieve(unsigned int number) {
	// sets "NOPRIME = 1"
	unsigned char *p = psieve + number/8;
	*p |= 1 << number%8;
}

int get_sieve(unsigned int number) {
	// if "NOPRIME" return code > 0
	unsigned char *p = psieve + number/8;
	return *p & (1 << number%8);
}

int get_primes(unsigned int max_number) { 
    unsigned int np = 2;
    unsigned int m, p;
 
    set_sieve(0);
    set_sieve(1);
    do {
		m = np + np;
		while(m <= max_number) {
			set_sieve(m);
			m += np;
		}
		while(++np <= max_number && get_sieve(np) > 0)
			;
    } while (np <= max_number);
	// fill primes array
    for (m=p=0; p <= max_number; p++) {
        if (get_sieve(p) == 0) {
			*(pprime + m) = p;
			m++;
		}
	}
	return m;		
}

int factorize(unsigned int number) {
	unsigned int pnum; 
	int np=0, nf=0;

	while (number > 1) {
		pnum = *(pprime + np);
		while (number % pnum == 0) {
			*(ppfact + nf++) = pnum;
			number /= pnum;
		} 
		if (++np >= nprime)
			return 0;
	}
	return nf;
}

int main(int argc, char **argv) {
	unsigned int max_number, number;
	unsigned int pfact, gtest, k;

	if (argc <= 1 || (max_number = atoi(argv[1])) == 0)
		return 1;

	printf("Berechne Primzahlen bis %d...\n", MAX_SIEVE);
	alloc_buffers();
    nprime = get_primes(MAX_SIEVE);
	printf("%d Primzahlen gefunden.\n",nprime);

   	printf("Suche Giuga-Zahlen bis %u\n", max_number);
    for (number=2; number <= max_number; number+=2) {
	    gtest = 1;
	    if ((npfact = factorize(number)) > 0) {
		  gtest = pfact = 0;	
		  for (k=0; k < npfact; k++) {
		    if (pfact < *(ppfact + k)) {
			    pfact = *(ppfact + k);
		        if ((gtest += (number>pfact)?(number/pfact-1)%pfact:1) > 0)
		          break;
  		    }
  		  }  
	    }
        if (gtest == 0) {
			// Treffer
			printf("%u = ", number);
		    for (k=0; k < npfact; k++)
				printf("%u%c", *(ppfact + k), (k<npfact-1)?'*':'\n');
		}	
	}	
	free_buffers();
    return 0;
}

Kommentare:

Für diese Lösung gibt es noch keinen Kommentar

Bitte melden Sie sich an um eine Kommentar zu schreiben.
Kommentar schreiben
1822868

Du scheinst einen AdBlocker zu nutzen. Ich würde mich freuen, wenn du ihn auf dieser Seite deaktivierst und dich davon überzeugst, dass die Werbung hier nicht störend ist.