Re: Was ist falsch an meinem code?
Verfasst: Montag 8. Juli 2013, 23:33
@Gwunderi: Durch Deine for-Schleife hast Du die »and«-Verknüpfung in eine »or«-Verknüpfung umgewandelt.
Seit 2002 Diskussionen rund um die Programmiersprache Python
https://www.python-forum.de/
Code: Alles auswählen
import java.util.*;
public class PrimeCalculator {
public static List<Integer> getPrimes(int limit) {
List<Integer> primes = new ArrayList<Integer>();
if (limit < 2) {
return primes;
}
primes.add(2);
for (int i = 3; i <= limit; i += 2) {
boolean isPrime = true;
for (int prime : primes) {
if (i % prime == 0) {
isPrime = false;
break;
}
}
if (isPrime) {
primes.add(i);
}
}
return primes;
}
public static int getLargestPrimeFactor(int n) {
if (n < 2) {
throw new IllegalArgumentException("n must be >= 2");
}
List<Integer> candidates = getPrimes(n / 2);
Collections.reverse(candidates);
int result = -1;
for (int candidate : candidates) {
if (n % candidate == 0) {
result = candidate;
break;
}
}
return result;
}
public static void main(String[] args) {
System.out.println(getLargestPrimeFactor(111));
}
}Jepp. Auf meinem Rechner sorgt schon die Ausführung mit größeren 6-stelligen Zahlen eine spürbare Wartezeit.jerch hat geschrieben:@snafu:
An dem Sieb lässt sich aber noch einiges optimieren
Code: Alles auswählen
# input %rax = number to factor
# output %rax = largest prime factor
primfac:
movq $2, %rcx
jmp _start
_loop:
xorq %rdx, %rdx
divq %rcx
orq %rdx, %rdx
jne _cont
_start:
cvtsi2sdq %rax, %xmm0
sqrtsd %xmm0, %xmm0
cvttsd2siq %xmm0, %rdi
movq %rax, %rsi
jmp _test
_cont:
incq %rcx
movq %rsi, %rax
_test:
cmpq %rdi, %rcx
jle _loop
ret
Code: Alles auswählen
public class PrimeCalculator {
public static int getLargestPrimeFactor(int n) {
while (n % 2 == 0) {
n /= 2;
}
int result = 2;
for (int i = (int) Math.sqrt(n); i < n; i++) {
double j = Math.sqrt(i * i - n);
if (j == (int) j) {
// Quadratzahl gefunden
result = i + (int) j;
break;
}
}
return result;
}
public static void main(String[] args) {
System.out.println(getLargestPrimeFactor(486847));
}
}Da es maximal einen Primfaktor größer sqrt(n) geben kann, kannst Du diesen ganz leicht ausrechnen: p_max = n / (p_1^a * p_2^b ...)snafu hat geschrieben:@jerch: Das mit der oberen Suchgrenze verstehe ich nicht. Es wurde ja schon angesprochen, dass es desöfteren Situationen gibt, wo der größte Primfaktor *größer* als die Quadratwurzel ist (z.B. bei 77). Wie würde man da im Detail vorgehen?
Code: Alles auswählen
#!/usr/bin/env node
'use strict';
var _ = require('underscore');
var createPrimeGenerator = function () {
var primes = [2];
var candidate = 1;
var testCandidate = function (prime) { return candidate % prime != 0; };
var next = function () {
next = function () {
while (true) {
candidate += 2;
if (_(primes).every(testCandidate)) {
primes.push(candidate);
return candidate;
}
}
};
return 2;
};
return function () { return next(); };
}
var factor = function (n) {
var result = [];
var getNextPrime = createPrimeGenerator();
while (n > 1) {
var prime = getNextPrime();
if (n % prime == 0) {
result.push(prime);
while (n > 1 && n % prime == 0) n /= prime;
}
}
return result;
}
var main = function () {
console.log(factor(parseInt(process.argv[2])));
};
main();Ach so, und da alle anderen geprüften Zahlen keine Teiler von 486'847 sind, wird sie ausgegeben. Hatte ja schon gesehen, dass die Lösungen gleich mehrfach ausgegeben werden, dachte mir aber, es sei weil jetzt jede Zahl einzeln geprüft wird, was ja auch stimmt - aber dass die "and"-Verknüpufng damit auch verlorengeht ... wäre eigentlich logisch. (Und da es dieselben Ergebnisse lieferte, habe ich gar nicht weiter überlegt.)Sirius3 hat geschrieben:Durch Deine for-Schleife hast Du die »and«-Verknüpfung in eine »or«-Verknüpfung umgewandelt.
Code: Alles auswählen
if all(a%x>0 for x in prime_proof): ...Code: Alles auswählen
primteiler = [2]
n = int(input("Gib eine ganze Zahl ein: "))
a = 3
while a <= n/2:
if all(a%x > 0 for x in primteiler) and n%a == 0:
primteiler.append(a)
a = a + 2
print(primteiler)
Code: Alles auswählen
from itertools import count, takewhile
def get_largest_prime_factor(n):
if n < 2:
raise ValueError('n must be >= 2')
for candidate in takewhile(lambda i: i <= n, count(2)):
while n % candidate == 0:
n /= candidate
return candidateGwunderi hat geschrieben:Hallo zusammen,
Habe auch ein paar Anmerkungen:
Will man prüfen, OB eine Zahl n eine Primzahl ist, genügt es, bis zur Wurzel von n zu prüfen.
Aber um die grösste Primzahl, die Teiler von n ist herauszufinden genügt es nicht, habe ich eben herausgefunden.
Nehmen wir z.B. 33 - ist 33 eine Primzahl? da genügt es, bis 6 zu prüfen, denn 11 * 3 wurde schon bei der 3 geprüft.
Aber die grösste Primzahl, die Teiler von 33 ist - also 11 - würde man hier glatt "übersehen".
Man muss also doch, wie BlackJack anfangs meinte, bis n/2 prüfen!
]
Code: Alles auswählen
from itertools import count, takewhile, chain
def get_largest_prime_factor(n):
if n < 2:
raise ValueError('n must be >= 2')
sqn=n**0.5
for candidate in takewhile(lambda i: i <= sqn, chain((2,), count(3, 2))):
while n % candidate == 0 and n>candidate:
n /= candidate
sqn=n**0.5
return nCode: Alles auswählen
from itertools import chain, count, takewhile
def get_largest_prime_factor(n):
if n < 2:
raise ValueError('n must be >= 2')
sqn = n**.5
candidates = chain([2], count(3, 2))
for candidate in takewhile(lambda i: i <= sqn, candidates):
while n % candidate == 0:
n /= candidate
sqn = n**.5
return candidateCode: Alles auswählen
from math import sqrt
def prime_factors(n):
sq_n = sqrt(n)
counter = 0
candidate = 2
while candidate <= sq_n:
while not n % candidate:
n /= candidate
sq_n = sqrt(n)
counter += 1
if counter:
yield (candidate, counter)
counter = 0
if candidate == 2:
candidate += 1
else:
candidate += 2
if n > 1:
yield (n, 1)
def pprint_factors(factors):
return ' * '.join('%d^%d' % (b, e) if e > 1 else '%d' % (b,)
for b, e in factors)