Přidat otázku mezi oblíbenéZasílat nové odpovědi e-mailem Da sa lepsie ? Overovac, generator prvocisel. Python 3.

Nikde nie su zaciatocnicke cvicenia pre python 3 programovanie. Z obavy ze vsetko zabudnem, vymyslel som si toto zadanie.

Algoritmus som zalozil na tomto:
[YDxKzg3.png]

Toto je jednoduchsi skript pre input jedneho cisla pre overenie:
345EFMC
Gro zistovanie je zabalene v meraci CPU casu. Ze kolko to cele trvalo vyratat.
Na mojom starom pc(sekundy):
14 miestne: 55555544444441 4.8984314
15 miestne: 101103107109113 6.4584414
15 miestne: 111111151111111 6.723643099999999
15 miestne: 988666444411111 19.6249258
16 miestne: 6171054912832631 50.123121299999994

Toto je zlozitejsi skript pre input hornej hranice. Program postupuje od zaciacku (cislo 2):
A
Tu je casomerac umiestneny lepsie. Mal by merat presnejsie iba vypocty:
3ZSXE0D
Ale ak zadam cislo: 999999, trva mu to 62 sekund. Dlhsie ako horsie umiestnenemu koncu casomeraca v pripade B(po list.append()):

B
05QDZEX
Takto to pri tom istom cisle trva 43 sekund. Ako je to mozne ?

Daju sa skripty napisat lepsie, aby bol kratsi cas /mensi vykon potrebny na vyratanie ?

Předmět Autor Datum
Proč si ukládáš nalezená prvočísla, když je pak nepoužíváš pro kontrolu dalších čísel?
Wikan 24.05.2016 21:04
Wikan
Preco sa zase nezaoberate mojim dotazom ale svojim vlastnym ?
IT_lamiak 24.05.2016 21:12
IT_lamiak
Ptal ses, jak to napsat lépe, aby to bylo rychlejší. No ale vidím, že umíš jenom prskat kolem sebe a…
Wikan 24.05.2016 21:22
Wikan
Nie, ty si nepochopil celkovy dotaz alebo zase necitas pozorne. OVEROVAC cisel ci je zadane cislo pr…
IT_lamiak 24.05.2016 21:25
IT_lamiak
Ale já ti napsal, jak to napsat lépe. Použití už jednou nalezených prvočísel celý proces mnohonásobn…
Wikan 24.05.2016 21:28
Wikan
Ozaj nechapem, ved ja som to napisal najlepie ako som vedel. Nic sa tam neopakuje. Pred hlavnou naro…
IT_lamiak 24.05.2016 21:31
IT_lamiak
Právě ta brute force detekce je největší brzda. Procházíš tam všechna čísla od num až do odmocniny z…
Wikan 24.05.2016 21:36
Wikan
Neviem ako sa dajú písať skripty v Pythone lepšie, ale zrejme ten Tvoj algoritmus nestojí za veľa...…
pme 24.05.2016 22:27
pme
Optimalizacia sa robi bud optimalizaciou algoritmu, alebo optimalizaciou vnutornych cykov, alebo nap…
MM.. 25.05.2016 01:23
MM..
A je logicke ze ked do najvnutornejsieho cyklu ktory sa vykonava trilionkrat a v ktorom je defakto l…
MM.. 25.05.2016 01:32
MM..
Alebo elif numb % 2 == 0: # evens excluded continue elif num % numb == 0: # not prime break co t…
MM.. 25.05.2016 01:38
MM..
Pre poriadok. Toto je povodny vytvor s casom 40 s, pri inpute 999999. 05QDZEX @ Wikan: Upravil som…
IT_lamiak 25.05.2016 16:52
IT_lamiak
Tohle vypadá divně: if num % element == 0: # already found primes scan break else: list_of_primes.…
Wikan 25.05.2016 17:03
Wikan
Nie, je to v poriadku. Pozeral som to tuto krok za krokom. Chod sem: visualize.html Pastni tam ten k…
IT_lamiak 25.05.2016 17:27
IT_lamiak
Zkusil jsem tohle: 07MHFHV Chodí to docela rychle, ale pořád je místo pro optimalizace.
Wikan 25.05.2016 18:19
Wikan
Nemusis nic prevadzat na string. testovanie prvocisel je jedno delenie v cykle. NIC VIAC v tom cykle…
MM.. 25.05.2016 17:25
MM..
Mozes cely post rozpisat ako si to myslel ? Nechytam sa vobec
IT_lamiak 25.05.2016 17:29
IT_lamiak
Vyhod vsetky prevody na string a vsetky nezmysly ktore ten string pouzivaju.
MM.. 25.05.2016 17:31
MM..
a dalej ? to riesenie som chcel precitat normalnejsie ako vysvetlis, ze optimalnejsie riesenie Wika…
IT_lamiak 25.05.2016 17:36
IT_lamiak
Ja neviem co robi Wikanove riesenie necital som to, ale ty robis blbo uplne vsetko.
MM.. 25.05.2016 17:43
MM..
upravene "tvoje" riesenie (bez vyuzivania doterajsieho zoznamu prvocisel) user_input = int(input('W…
MM.. 25.05.2016 18:13
MM..
ok dik len pockaj chvilu, zistil som ze to wikanove riesenie asi bude rychlejsie(prepac wikanko. aj…
IT_lamiak 25.05.2016 18:23
IT_lamiak
Nedavaj tam ziadne indexy, kontroluj cely list. A vyhod tie tvoje nezmyselne extra kontroly na 2,3 a…
MM.. 25.05.2016 18:25
MM..
wikan: nie je mozne to ohranicit indexom, lebo ciselny gap medzi prvocislami je random. neda sa to…
IT_lamiak 25.05.2016 21:45
IT_lamiak
Já ale o indexech nic nepsal. Proč jsi nepoužil to mé řešení? A pomalé je to proto, že tam neustále…
Wikan 25.05.2016 21:47
Wikan
ved som pouzil - prechadzal som uz ulozene prvocisla ako si povedal a prave som zistil ze to o 5 se…
IT_lamiak 25.05.2016 21:53
IT_lamiak
Myslím přímo ten kód, který jsem sem dával.
Wikan 25.05.2016 21:56
Wikan
Aha, nevsimol som si to. Tak pri 999999 to trvalo 8-9 sekund, teda dost mega efektivne. Hlava mi to…
IT_lamiak 25.05.2016 22:20
IT_lamiak
To tam neni zbytecne, ale prave proto, aby se to nepocitalo znovu pri kazdem pruchodu.
Wikan 25.05.2016 22:22
Wikan
MM.. mi hore napisal, ze kazde druhe cislo overovat, ze sa da priamo v cykle. a neda sa. teraz to ku…
IT_lamiak 25.05.2016 22:28
IT_lamiak
prosimta, co to tam zas lepis za nezmysel? Ja som nikde nepisal ze mas delit nieco s numb+2. A dal s… poslední
MM.. 26.05.2016 01:11
MM..

Nie, ty si nepochopil celkovy dotaz alebo zase necitas pozorne.
OVEROVAC cisel ci je zadane cislo prvocislo. To mam, nic dalsie s tym nechcem robit, ale sa pytam, ci sa to da napisat lepsie !?

Dalsi skript je GENERATOR prvocisel z celkoveho range cisel. To tiez funguje tak ako chcem, len sa pytam na to co som sa pytal.

TAK PRECO mi nasilu nukas dalsie operacie co ma nezaujimaju ???

Ozaj nechapem, ved ja som to napisal najlepie ako som vedel. Nic sa tam neopakuje. Pred hlavnou narocnou brute force detekciou pomocou odmocniny, som predtym napisal co najviac vyradovacich kol, aby sa pracovalo s co najmensim poctom cisel.

Skus mi to este inac vysvetlit. Najlepsie konkretne ktore riadky.
Skusal si vobec tie skripty ?

Dik

Optimalizacia sa robi bud optimalizaciou algoritmu, alebo optimalizaciou vnutornych cykov, alebo napisanim to v niecom low level. Prva vec viz Wikan, druha vec zbytocne milionkrat v cykle testujes 2,3,5 to snad staci raz pred cyklom, prevadzas tam cisla na stringy (OMG), pouzivaj len delenie a nic neprevadzaj na stringy, delenie je 1 alebo par CPU clockov. Prevod na string je trilion clockov. Cele to je nezmysel. A ten treti bod, da sa to napisat v assembleri, potom to bude optimalne.

P.S. stringy budes potrebovat az ked sa to cislo nezmesti do 64bitov apod, ale to zas nemozes prevadzat zo ziadneho "num", ptz sa to potom ako cislo vobec ulozit neda, a je nutne to drzat v stringu od zaciatku

A je logicke ze ked do najvnutornejsieho cyklu ktory sa vykonava trilionkrat a v ktorom je defakto len par deleni (par CPU cyklov) strcis volanie nejakej process_time fcie ktora potrebuje trilion CPU cyklov, tak to bude trvat o polovicu dlhsie. Navyse to volanie tam je este aj zbytocne.

Alebo

                elif numb % 2 == 0:             # evens excluded
                    continue  
                elif num % numb == 0:           # not prime
                    break                    

co to je za blbost? Ked jedno delenie num % numb trva cas X, a vies s nim priamo overit ze ci to je prime, tak naco tam strkas pred to zbytocnu operaciu numb % 2, takto ti to trva cas 2*X t.j. 2*dlhsie. Optimalizacia je o ZMENSOVANI poctu operacii, a ne o zvacsovani. Ked chces preskakovat parne cisla tak sa to da robit rovno v cykle ze sa robi cislo+2, a ne cislo+1. Jak sa to robi v tom python scripte si najdi sam, ja take neoptimalne veci nepouzivam.

Pre poriadok. Toto je povodny vytvor s casom 40 s, pri inpute 999999.
05QDZEX

@ Wikan:
Upravil som to podla tvojej rady nasledovne:
0946RQM
Ale cas sa vysplhal uplne inde. Po vyse 2 minutach som to zrusil.

@ pme:
Mam takyto CPU: 2 jadrovy: Intel(R) Core(TM)2 Duo CPU P8400 @ 2.26GHz
Ale aj mne sa zda, ze to trva akosi dlho.

@ MM..:
Na stringy musim previest koncovu cislicu cisla, lebo int sa neda indexovat ani iterovat, neni subscriptable. To iste plati pri sucte cifier cisla.

Inak sa koniec casomeracu neda umiestnit, aby som sa vyhol list.append().

"Ked jedno delenie num % numb trva cas X, a vies s nim priamo overit ze ci to je prime, tak naco tam strkas pred to zbytocnu operaciu numb % 2, takto ti to trva cas 2*X t.j. 2*dlhsie. Ked chces preskakovat parne cisla tak sa to da robit rovno v cykle ze sa robi cislo+2"
- Upravil som povodny vytvor a teda toto:

            for numb in range(int(num ** 0.5) + 1):  # square root brute force check
                if numb < 7:
                    continue
                elif numb % 2 == 0:             # evens excluded
                    continue  
                elif num % numb == 0:           # not prime
                    break                    
            else:
                list_of_primes.append(num)

som nahradil tymto:

            for numb in range(7, int(num ** 0.5) + 1):  # square root brute force check
                if num % (numb + 2) == 0:               # not prime, evens excluded
                    break                    
            else:
                list_of_primes.append(num)

a usetrilo sa 5 sekund :)

Nemusis nic prevadzat na string. testovanie prvocisel je jedno delenie v cykle. NIC VIAC v tom cykle nema byt. TO je najoptimalnejsie. (a cyklus ma mat krok 2).
P.S. az prestanes pouzivat integery uplne (vyssi level co sa tyka velkosti cisla) tak potom je to nieco uplne ine. Ak sa len hras ze pouzivas integery tak nerob ziadne somariny vnutri cyklu a ani nic neprevadzaj na stringy.

upravene "tvoje" riesenie (bez vyuzivania doterajsieho zoznamu prvocisel)

user_input = int(input('Write number for all primes up to(included): '))
list_of_primes = []
from time import process_time
t = process_time()

#BLBOSTI VON Z CYKLU
if user_input >= 2:
        list_of_primes.append(2)
if user_input >= 3:
        list_of_primes.append(3)
if user_input >= 5:
        list_of_primes.append(5)

num = 7
while num <= user_input:   #PRVY CYKLUS BEZ BLBOSTI
        numb = 3
        konec = (num ** 0.5) + 1
        while numb <= konec:  #DRUHY CYKLUS BEZ BLBOSTI
            if num % numb == 0:           # not prime
                    break 
            numb = numb + 2   # KROK DVA
        else:
            list_of_primes.append(num)
        num = num + 2         # KROK DVA

neviem ci to je syntakticky spravne nepoznam python. Toto trva kolko?

ok dik len pockaj chvilu, zistil som ze to wikanove riesenie asi bude rychlejsie(prepac wikanko. aj ked asi nie o vela, lebo vypadne len par cisel), len ja som zabudol zadat limit hornej hranice.
malo to byt takto:

        else:
            summ = 0
            for element in list_of_primes[3:list_of_primes.index(int(num ** 0.5))]:  # start from prime 7
                if num % element == 0:                                               # already found primes scan
                    break
            else:
                list_of_primes.append(num)

lenze mi vyhadzuje chybu, ked kontroluje cislo 17.
lebo odmocnina je 4 a to nie je v nasom liste prvocisel. tuto list.index(value) metodu potrebujem upravit, ze ked nenajde presne to cislo, tak nech zoberie najblizsie nizsie prvocislo. lenze, do indexu nemozem dat boolean, lebo vyjde nie cislo ale True alebo False. teraz neviem co spravit

wikan:

nie je mozne to ohranicit indexom, lebo ciselny gap medzi prvocislami je random. neda sa to spravit.

tak som to vymyslel takto:

            for element in list_of_primes: 
                if element <= int(num ** 0.5): 
                    if num % element == 0:                                               # already found primes scan
                        break

lenze uz pri malom inpute: 99999, to trvalo 47 sekund !

nechapem ako je to mozne, ked logicky, tymto prechadzam mensim poctom cisel ako tomu bolo tu:

            for numb in range(7, int(num ** 0.5) + 1):  # square root brute force check
                if num % (numb + 2) == 0:               # not prime, evens excluded
                    break                    

uz neviem co s tym

Aha, nevsimol som si to.
Tak pri 999999 to trvalo 8-9 sekund, teda dost mega efektivne. Hlava mi to nebere.
Nakolko nemam rad, ked vsade lietaju variabilne zbytocne definovane, tak som ti zrusil 'maximum' a napisal som to priamo do kodu:

povodne:

for num in our_range:
    maximum = num ** 0.5
    for prime in list_of_primes:
        if prime > maximum:
            list_of_primes.append(num)
            break
        if num % prime == 0:
            break
print(list_of_primes)

prerobene:

for num in our_range:
    for prime in list_of_primes:
        if prime > num ** 0.5:
            list_of_primes.append(num)
            break
        if num % prime == 0:
            break
print(list_of_primes)

takto prerobene to trvalo 14-15 sekund. nechapem preco

MM.. mi hore napisal, ze kazde druhe cislo overovat, ze sa da priamo v cykle. a neda sa. teraz to kukam vo vizualizeri, a vobec neberie do uvahy tuto linu:

                if num % (numb + 2) == 0:               # not prime, evens excluded

stale berie numb a nie numb+2
preto to pocita hovadiny, ale ako je potom mozne ze aj tak to preslo o 5 sekund rychlejsie ?

Zpět do poradny Odpovědět na původní otázku Nahoru