C :: Aufgabe #70 :: Lösung #1
4 Lösungen
#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
Schreibe ein Programm welches alle Giuga-Zahlen bis zu einer festen Obergrenze ausgibt.
Erläuterung zu einer Giuga-Zahl findest du hier: Wikipedia
#1
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
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
Seite 1 von 0
1