C :: Aufgabe #70
4 Lösungen
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
Lösungen:
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;
}
// Giuga Zahlen.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "stdlib.h"
#include "math.h"
struct element
{
int key;
int zahl;
struct element *next;
};
void append(struct element **liste, int value)
{
struct element *neuesElement;
struct element *liste_iter = *liste;
neuesElement = (struct element*)malloc(sizeof(struct element));
neuesElement->zahl = value,
neuesElement->next = NULL;
if(liste_iter != NULL)
{
while(liste_iter->next != NULL)
{
liste_iter = liste_iter->next;
}
liste_iter->next = neuesElement;
neuesElement->key = liste_iter->key+1;
}
else
{
*liste = neuesElement;
neuesElement->key = 0;
}
}
void printliste(struct element *list)
{
printf("das %d element hat den wert %d\n",list->key, list->zahl);
while (list->next != NULL)
{
list = list->next;
printf("das %d element hat den wert %d\n",list->key, list->zahl);
}
printf("\n\n");
}
element *Prim(int grenze)
{
struct element *primListe;
primListe = NULL;
int teiler = 0;
int j;
for(int i = 2; i <= grenze; i++)
{
for(j = (i-1); i%j; j--)
{
}
if(j == 1)
{
append(&primListe,i);
teiler = i;
}
}
return primListe;
}
int ifPrim(int zahl, struct element *primKey)
{
while(zahl != primKey->zahl && primKey->next != NULL)
{
primKey = primKey->next;
if(primKey->zahl == zahl)
{
//printf("Zahl ist eine Primzahl");
return 1;
break;
}
if(primKey->zahl > zahl)
{
//printf("Zahl ist keine Primzahl");
return 0;
break;
}
}
}
element *primTeiler(int zahl, int primzahlen)
{
struct element *primKey = Prim(primzahlen);
struct element *primKey_start = primKey;
struct element *primTeiler;
primTeiler = NULL;
int zahl_start = zahl;
if(!ifPrim(zahl, primKey))
{
while( zahl > 1 )
{
while(zahl % primKey->zahl == 0)
{
//printf("%d * ",primKey->zahl);
append(&primTeiler, primKey->zahl);
zahl = zahl / primKey->zahl;
}
primKey = primKey->next;
if(ifPrim(zahl, primKey_start))
{
//printf("%d = %d\n\n",zahl,zahl_start);
append(&primTeiler, zahl);
break;
}
if(zahl % primKey->zahl != 0)
{
primKey = primKey->next;
}
}
}
else
{
primTeiler = NULL;
}
return primTeiler;
}
void Giuga(int zahl)
{
struct element *PT = primTeiler(zahl, 10000);
if(PT != NULL)
{
while(PT->next != NULL)
{
//printf("%d\n",PT->zahl);
if( ((zahl / PT->zahl) -1) % PT->zahl == 0 )
{
//printf("%d ist ein Teiler von %d / %d -1\n", PT->zahl, zahl, PT->zahl);
PT = PT->next;
}
else
{
//printf("\nDie Zahl %d ist keine Giuga Zahl\n",zahl);
break;
}
if(PT->next == NULL)
{
if( ((zahl / PT->zahl) -1) % PT->zahl == 0 )
{
//printf("%d ist ein Teiler von %d / %d -1\n", PT->zahl, zahl, PT->zahl);
//printf("\nDie Zahl %d ist eine Giuga Zahl\n",zahl);
printf("%d\tGiuga\n",zahl);
}
}
}
}
else
{
printf("%d\tPrimzahl\n",zahl);
}
}
int main()
{
for(int i = 0; i<1000; i++)
{
int zahl = i;
Giuga(zahl);
}
getchar();
return 0;
}
#define LIMIT 1000000
#include <stdio.h>
void getSmallestFactor(int array[]) {
int i, j;
for (i = 2; i * i <= LIMIT; i++) {
if (array [i] == 0) {
for (j = 2 * i; j <= LIMIT; j += i) {
if (array [j] == 0) {
array [j] = i;
}
}
}
}
}
int isGiuga(int n, const int primes[]) {
int current = n;
while (primes[current] != 0) {
if ((n / primes [current] - 1) % primes [current] != 0)
return 0;
current /= primes [current];
}
return n != current && (n / current - 1) % current == 0;
}
int main() {
int primes[LIMIT + 1] = {0};
int i;
getSmallestFactor (primes);
for (i = 1; i <= LIMIT; i++) {
if (isGiuga (i, primes)) {
printf("%i\n", i);
}
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int main(void)
{
int grenze, zahl, z, i, p, anzahl_faktoren;
bool gefunden, giuga;
int faktoren[100]={0};
printf("Bis zu welcher Grenze sollen die Giuga Zahlen berechnet werden? \n");
if (scanf("%d", &grenze)!=1) {
printf("Zahl wurde falsch eingegeben. \n");
return EXIT_FAILURE;
}
fflush(stdin);
printf("\n***************************");
printf("\n*** Giuga Zahlen bis %d ", grenze);
printf("\n***************************\n\n");
for (zahl=2;zahl<=grenze;zahl++)
{
//faktoren[100] = {0};
anzahl_faktoren=0;
giuga = true;
//Primfaktorzerlegung
z=zahl;
while (z>1) {
i =2;
gefunden = false;
while(i*i<=z && gefunden == false) {
if (z%i == 0) {
gefunden = true;
p=i;
}
else
i++;
}
if (gefunden == false)
p=z;
faktoren[anzahl_faktoren] = p;
anzahl_faktoren++;
z = z / p;
}
//Prüfe auf Giuga Zahl
for (i=0;i<anzahl_faktoren;i++) {
if (((zahl/faktoren[i])-1)%faktoren[i]!=0 || ((zahl/faktoren[i])-1)==0)
giuga = false;
}
if (giuga==true)
printf("%d \t", zahl);
}
}
