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.
C-Code
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
/********************************************
* 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
