Tváří v tvář MemoryError v Pythonu

Napsal jsem program pro nalezení hlavních faktorů čísla. Když zadám jako vstup velké číslo (600851475143), objeví se MemoryError. Níže je uveden kód:

def fact(a): factors = [] for i in range(1,a+1): if a%i == 0: factors.append(i) return factors num = raw_input(">> ") #600851475143 a = b = [] a = fact(long(num)) for i in range(0,len(a)): b = fact(a[i]) if len(b) <= 2: print a[i] 

Při procházení jsem zjistil, že Python využívá počítačovou paměť – RAM. Používám Python v Unbuntu beze změny jeho konfigurace. Měl bych změnit anythig na práci na 64bitovém počítači. Nebo bych měl použít tuto funkci k obcházení této chyby?

Komentáře

  • Základním problémem je, že váš algoritmus pravděpodobně používá příliš mnoho Paměť. Pokud používáte python 2, range(1, a+1) se pokouší vytvořit seznam s 600851475143 prvky. To pravděpodobně není to, co chcete, protože každý prvek bude celé číslo a každé celé číslo trvá 4 bajty. (Také tato otázka není ' vhodná pro programátory, protože opravdu potřebujete kontrolu kódu a zejména pochopit, jak funguje python.)
  • (Pravděpodobně chcete xrange, což je generátor, který vrací prvky do smyčky for podle potřeby. To však nemusí být jediný problém, který máte .)
  • Váš seznam je velký 2,2 TB. Přechod na 64bitový stroj nepomůže. Musíte nainstalovat více než 2 TB RAM (což bude spravedlivé vyžadovat použití 64bitového OS). Nebo si znovu promyslete svůj algoritmus.
  • Kromě problémů s pamětí (jen proto, že na to zatím nikdo jiný neupozornil), existují některé účinnější algoritmy pro výpočet seznamu faktorů čísla nebo pro rozhodnutí ať už je číslo prvočíslo, nebo vygenerovat seznam prvočísel. Zatímco většina lidí mluví o časové složitosti , existuje také související koncept prostorové složitosti .

Odpověď

Existuje několik způsobů, jak měřit paměť používanou vaším programem, a můžete zvýšit limity pro jednotlivé uživatele nebo tak něco.

Nejprve však nemusíte alokovat tuto paměť, protože stačí vygenerovat sekvenci bez uložení všech:

def fact(a): "just return a generator for the sequence you want" return (i for i in xrange(1,a+1) if a % i == 0) 

Upozorňujeme, že můžete iterovat i přímo nad sekvencemi, aniž byste je museli opakovaně indexovat:

for b in fact(long(num)): print b 

Komentáře

  • Seznam v otázce je velký 2,2 TB, pochybuji, že zvýšení limitů zdrojů pomůže 😀
  • No, možná OP může počkat do roku 2035, kdy K dispozici jsou 8 TB SIMMS.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *