Na forum 4programmers.net korzystamy z plików cookies. Część z nich jest niezbędna do funkcjonowania
naszego forum, natomiast wykorzystanie pozostałych zależy od Twojej dobrowolnej zgody, którą możesz
wyrazić poniżej. Klikając „Zaakceptuj Wszystkie” zgadzasz się na wykorzystywanie przez nas plików cookies
analitycznych oraz reklamowych, jeżeli nie chcesz udzielić nam swojej zgody kliknij „Tylko niezbędne”.
Możesz także wyrazić swoją zgodę odrębnie dla plików cookies analitycznych lub reklamowych. W tym celu
ustaw odpowiednio pola wyboru i kliknij „Zaakceptuj Zaznaczone”. Więcej informacji o technologii cookie
znajduje się w naszej polityce prywatności.
Cześć. Mam taki oto program do generowania liczb pierwszych i niestety nie chce mi działać. Właściwie to wypisuje mi tylko "1" w tablicy. Czy ktoś mógłby na to popatrzeć? ;)
Kopiuj
def wyznacz_pierwsze(n):
pierwsze=[]
a=2
for i in range (2, n):
if a%i==0:
break
else:
pierwsze.append(a)
a+=1
pierwsze.insert(0,1)
return pierwsze
print(wyznacz_pierwsze(300))
Ten program sprawdza tylko podzielność przez 2, poprawny będzie np taki:
Kopiuj
pierwsze =[2]defczy_pierwsza(liczba):for dzielnik in pierwsze:if liczba % dzielnik ==0:returnFalseif dzielnik * dzielnik > liczba:returnTruereturnTruedefwyznacz_pierwsze(liczba):for i inrange(2, liczba):if czy_pierwsza(i)isTrue:
pierwsze.append(i)return
wyznacz_pierwsze(300)print(pierwsze)
Twój kod nie działa, wiadomo dlaczego. Potrzeba funkcji is_prime:
Kopiuj
defis_prime(n):if n ==2or n ==3:returnTrueif n %2==0or n %3==0:returnFalse
limit =int(math.sqrt(n))
k =1while6* k -1<= limit or6* k +1<= limit:if n %(6* k -1)==0or n %(6* k +1)==0:returnFalse
k +=1returnTrue
defget_primes_gen(n):whileTrue:if is_prime(n):yield n
n +=1
Nie Musisz ich teraz pakować naraz do listy, tylko pobrać ile Chcesz z generatora, na przykład iterując go w pętli czy używając metod (opisane w linku).
Sa też specjalne algorytmy do generowania liczb pierwszych, na przykład Sito Erastotenesa: https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
Kopiuj
import math
deferastotenes_sieve(n):
arr =[True]* n
limit =int(math.sqrt(n))+2for i inrange(2, limit):
j = i**2
k =0while j < n:
arr[j]=False
k +=1
j = i**2+ k * i
out_val =[]for m inrange(2,len(arr)):if arr[m]==True:
out_val.append(m)return out_val
Jak na Pythona to nawet, znajduje primes do 100 milionów w 32.5 sek.
Liczenie pierwiastka czyli Math.sqrt() tylko spowolni program, przy pierwszych nie warto go stosować. swoją drogą w Pythonie można tworzyć funkcję wewnątrz funkcji. Dzięki czemu możesz zrobić tak:
Kopiuj
defwyznacz_pierwsze(liczba):
pierwsze =[2]defczy_pierwsza(liczba):for dzielnik in pierwsze:if liczba % dzielnik ==0:returnFalseif dzielnik * dzielnik > liczba:returnTruereturnTruefor i inrange(2, liczba):if czy_pierwsza(i)isTrue:
pierwsze.append(i)return pierwsze
print(wyznacz_pierwsze(300))
Liczenie pierwiastka trwa dużo dłużej niż mnożenie, wiec wydaje mi się że moje rozwiązanie lepsze. No chyba żeby np wyszukiwaniem binarnym znaleźć jego część całkowitą (to co po przecinku w tym przypadku nie ma znaczenia), tylko czy wtedy nie będzie to strzelanie z armaty do wróbla?
@sig: Hm... Sugerujesz, ze policzenie raz pierwiastka z liczby n jest wolniejsze, niz pierwiastek z n mnozenie(I porownan). Ciekawe, nie wydaje mi sie, twierdze wrecz przeciwnie, zreszta Mozesz sprawdzic
Przy pierwiastku masz od cholery zapętleń i działań na liczbach zmiennoprzecinkowych.
Zerknij w module math ile warunków i działań jest wykonywanych przy sqrt. To jest wolniejsze niż sprawdzanie warunku z mnożeniem 100 tyś. razy.
Dla liczby 10**6 na moim sprzęcie bez jit'a.
next_test_pr (in sec): 0.03993 # 98.7257% faster than the slowest
lion_primes (in sec): 3.13345 # The slowest
Kopiuj
defnext_test(n=10**6):if n <100:return[i for i in(2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97)if i<n];
res =[2]; s =bytearray([0]); i =3; j =9;
nxt_i =lambda: i+2; nxt_j =lambda: i*i;
s *= n
defmo():
s[j::i+i]=bytearray([1])*int((n-(j))/(i+i)+1)
res.append(i)while j<n:
mo()ifnot s[i]elseNone
i = nxt_i(); j = nxt_j();return res +[g for g inrange(i, n,2)ifnot s[g]]
Co prawda można jeszcze szybciej z jeszcze mniejszym zużyciem pamięci wykorzystując cythona, ale to już powinno być wystarczająće, ale może ci posłuży mój algorytm ;p.
Najważniejsze tutaj to operować na fragmentach list, bo to potrafi ponad dziesięciokrotnie zoptymalizować program. (Srry za nie pythonowy zapis, ale na slajdzie musiało mi się zmieścić :)
@Edit: Takie wtrącenie co do sita euklidesa.
Na generator to łatwo przerobić, tylko wrzucasz inicjalizację w klasie dla wybranego przez siebie zakresu ;p.