Elcrian
Commander
- Registriert
- Feb. 2008
- Beiträge
- 2.493
Hallo zusammen,
ich versuche aktuell für Project Euler die Faktorisierungsmethode von Dixon in C zu programmieren, scheitere aber etwas an den Details und dem Verständnis, da sich die Beschreibungen des Algorithmus' im Netz etwas zu widersprechen scheinen.
Mein Verständis war bisher folgendes:
1) Bestimmte Faktorbasis k bis exp(0.5 * sqrt(log(N) * log(log(N))))
--> Ich nutze dazu das Sieb von Erathosthenes, da ich den Ranz für andere Euler-Probleme ohnehin geschrieben habe
2) Erzeuge x_i als ceil(sqrt(N)) < x_i < N mit einer linearen Folge x++ und faktorisiere als a_i % x_i^(2) % N
3) Wenn pk-glattes a_i (--> der größte Primfaktor von pk is < a_i) gefunden, speichere [x_i,a_i]
4) Speichere die Faktoren von a? Danach macht weder Wiki noch die anderen Artikel für mich viel Sinn...
Algorithmus:
Andere Methoden:
Eine meine Quellen meinte folgendes:
/*
* the exponents of the prime factors are converted into an exponent vector mod 2.
* For example, if the factor base is {2, 3, 5, 7} and the p(x) value is
* 30870, we have:
* 30870 = 2^1 * 3^2 * 5^1 * 7^3
*/
Da mein Ansatz:
Aber, ganz offen gesagt: Weder klappt das, noch verstehe ich den Zusammenhang hier...
Folgende Quellen:
https://en.wikipedia.org/wiki/Dixon's_factorization_method
https://de.wikipedia.org/wiki/Dixons_Faktorisierungsmethode
http://nptel.ac.in/courses/106103015/26
http://mathworld.wolfram.com/DixonsFactorizationMethod.html
http://people.mpi-inf.mpg.de/~csaha/lectures/lec19.pdf
http://www.cse.iitk.ac.in/users/manindra/CS681/2005/Lecture21.pdf
Daher: Kann mir jemand verraten wie ich bei meiner Auflistung an Punkt 4) weiter komme? Ich stehe wirklich auf'm Schlauch...
Disclaimer: Ich habe weder Informatik noch Mathe studiert und mache das privat aus Spaß an der Freude. Also bitte keine "Das ist doch sooo offensichtlich!"-Posts. Und meine leider nicht mehr vorhandenen Hausaufgaben macht auch keiner..
Allgemeine Frage: Die auskommentierten "free()" Aufrufe produzieren Fehler - warum eigentlich? C ist mir immer noch ein Rätsel...
ich versuche aktuell für Project Euler die Faktorisierungsmethode von Dixon in C zu programmieren, scheitere aber etwas an den Details und dem Verständnis, da sich die Beschreibungen des Algorithmus' im Netz etwas zu widersprechen scheinen.
Mein Verständis war bisher folgendes:
1) Bestimmte Faktorbasis k bis exp(0.5 * sqrt(log(N) * log(log(N))))
--> Ich nutze dazu das Sieb von Erathosthenes, da ich den Ranz für andere Euler-Probleme ohnehin geschrieben habe
2) Erzeuge x_i als ceil(sqrt(N)) < x_i < N mit einer linearen Folge x++ und faktorisiere als a_i % x_i^(2) % N
3) Wenn pk-glattes a_i (--> der größte Primfaktor von pk is < a_i) gefunden, speichere [x_i,a_i]
4) Speichere die Faktoren von a? Danach macht weder Wiki noch die anderen Artikel für mich viel Sinn...
Algorithmus:
Code:
long dixon(int N) {
int pk = exp(0.5 * sqrt(log(N) * log(log(N))));
int* P = getAllFromSieveOfEratosthenes(pk); // factor base
// Try to get x_i as ceil(sqrt(N)) < x_i < N and factorize as
// a_i % x_i^(2) % N. (de.wiki)
int x = 1, i = 0, j = 0;
int a = 0;
int y[N][2];
int* e[N];
printf("N: %i, pk: %i \n",N,pk);
for (x = ceil(sqrt(N)); x <= N; x++) {
a = (int) pow(x, 2) % N;
x++;
if (isBSmooth(a, pk)) {
y[i][0] = x; // x
y[i][1] = a; // p(x)
e[i] = getPrimeFactors(a); // factors of a
i++;
}
}
}
Andere Methoden:
Code:
/**
* Checks if x is B-smooth
* e.g. isBSmooth(1620,5) == true
* 1,620 has prime factorization 2^2 × 3^4 × 5; therefore 1,620 is
* 5-smooth because none of its prime factors are greater than 5
*/
bool isBSmooth(long x, int B) {
int* P = getPrimeFactors(x);
int i;
for (i = sizeof(P) / sizeof(int); i >= 0; i--) {
if (*(P + i) > B)
return false;
}
//free(P);
return true;
}
/*
* https://stackoverflow.com/questions/23287/largest-prime-factor-of-a-number
* Runs O(sqrt(n))
* @param n positive integer
* @return All the prime factors of a positive integer n
*/
int* getPrimeFactors(int n) {
int* factors = calloc(ceil(0.25 * n), sizeof(int));
int d = 2, i = 0, ct = 0;
while (n > 1) {
while (n % d == 0) {
*(factors + i) = d;
n /= d;
i++;
if(d != 0) ct++;
}
d++;
if (d * d > n) {
if (n > 1) {
*(factors + i) = n;
i++;
if(n != 0) ct++;
}
break;
}
}
// this counts as dynamic array, right?
int* fact = calloc(ct,sizeof(int));
memcpy(fact,factors,ct);
//free(factors);
return fact;
}
/*
* This is horrible style. I copied this from Problem7.c b/c I wanted to avoid
* tripple-overloading
* @returns all Primes <= limit
*/
int* getAllFromSieveOfEratosthenes(int limit) {
limit--;
const int UNMARKED = 1;
const int MARKED = 0;
long i = 0, j = 0, counter = 0;
long size = limit * 100; // Not exactly accurate. Might need some refining
int* primes = malloc(size * sizeof(int));
int* res = malloc(size * sizeof(int));
int lastPrime = 2;
// start at 2. Set all as prime
for (i = lastPrime; i < size; i++) {
// this kills 32bit-OS, since j*i will exceed 2^(32)-1 pretty quickly
*(primes + i) = UNMARKED;
}
*(primes + 2) = MARKED;
i = lastPrime;
// Starting from p^(2), enumerate its multiples by counting to n in increments of p, and mark them in the list
do {
for (j = i; (i * j) < size; j++) {
*(primes + j * i) = MARKED;
}
// Find the first number greater than p in the list that is not marked
for (j = lastPrime; j < size; j++) {
if (j > lastPrime && *(primes + j) == UNMARKED) {
// Let p now equal this new number
i = lastPrime = j;
// add to result
*(res + counter) = i;
// Increment prime-count
counter++;
break;
}
}
} while (counter < limit);
free(primes);
return res;
}
Eine meine Quellen meinte folgendes:
/*
* the exponents of the prime factors are converted into an exponent vector mod 2.
* For example, if the factor base is {2, 3, 5, 7} and the p(x) value is
* 30870, we have:
* 30870 = 2^1 * 3^2 * 5^1 * 7^3
*/
Da mein Ansatz:
Code:
int bf = 0, ct = 0, imax = 0;
int emax = sizeof(e) / sizeof(int);
int* expMat[emax];
for (i = 0; i < emax; i++) {
imax = sizeof(e[i]) / sizeof(int);
int v[imax][2];
*(expMat+i) = v;
for (j = 0; j < imax; i++) {
// if the current exponent is still being counted, increment
if(*(e[i]+i) == bf) {
ct++;
}
// re-set the buffer and store the value in the exponent vector
else {
v[i][0] = bf;
v[i][1] = ct;
bf = *(e[i]+i);
ct = 0;
}
}
}
Folgende Quellen:
https://en.wikipedia.org/wiki/Dixon's_factorization_method
https://de.wikipedia.org/wiki/Dixons_Faktorisierungsmethode
http://nptel.ac.in/courses/106103015/26
http://mathworld.wolfram.com/DixonsFactorizationMethod.html
http://people.mpi-inf.mpg.de/~csaha/lectures/lec19.pdf
http://www.cse.iitk.ac.in/users/manindra/CS681/2005/Lecture21.pdf
Daher: Kann mir jemand verraten wie ich bei meiner Auflistung an Punkt 4) weiter komme? Ich stehe wirklich auf'm Schlauch...
Disclaimer: Ich habe weder Informatik noch Mathe studiert und mache das privat aus Spaß an der Freude. Also bitte keine "Das ist doch sooo offensichtlich!"-Posts. Und meine leider nicht mehr vorhandenen Hausaufgaben macht auch keiner..
Allgemeine Frage: Die auskommentierten "free()" Aufrufe produzieren Fehler - warum eigentlich? C ist mir immer noch ein Rätsel...
Zuletzt bearbeitet: