Inför MemoryError i Python

Jag skrev ett program för att hitta huvudfaktorer för ett tal. När jag anger ett stort antal (600851475143) som inmatning dyker MemoryError upp. Nedan följer koden:

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] 

Efter att jag bläddrat fick jag veta att Python använder datorminne – RAM. Jag använder Python i Unbuntu utan att ändra dess konfiguration. Ska jag ändra något till att arbeta på 64-bitars maskin. Eller ska jag använda några ytterligare funktioner för att komma runt detta fel

Kommentarer

  • Din grundläggande fråga är att din algoritm sannolikt använder för mycket minne. Om du använder python 2 försöker range(1, a+1) att skapa en lista med 600851475143 element. Detta är förmodligen inte vad du vill eftersom varje element kommer att vara ett heltal och varje heltal tar 4 byte. (Den här frågan är inte ' t lämplig för programmerare eftersom du verkligen behöver en kodgranskning och särskilt förstå hur python fungerar.)
  • (Du vill förmodligen xrange, som är en generator som returnerar element till for -slingan efter behov. Det kan dock inte vara det enda problemet du har .)
  • Din lista är 2,2 TB stor. Att byta till en 64-bitars maskin hjälper inte. Du måste installera mer än 2 TB RAM-minne (för att vara rättvis krävs ett 64-bitars operativsystem för att använda). Eller tänk igenom din algoritm.
  • Förutom minnesproblem (bara för att inga andra har påpekat hittills), finns det några mer effektiva algoritmer för att beräkna listan över faktorer för ett nummer eller för att bestämma om ett tal är primtall eller för att generera en lista med primtal. Medan de flesta talar om tidskomplexitet , finns det också det relaterade begreppet rymdkomplexitet .

Svar

Det finns olika sätt att mäta minnet som används av ditt program, och du kanske kan öka per användare-gränser eller något.

Du behöver dock inte tilldela minnet i första hand, eftersom du bara kan generera sekvensen utan att lagra allt:

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) 

Observera att du också kan itera direkt över sekvenser utan att behöva indexera dem upprepade gånger:

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

Kommentarer

  • Listan i frågan är 2,2 TB stor, jag tvivlar på att höjda resursgränser kommer att hjälpa 😀
  • Tja, kanske OP kan vänta till 2035, när 8 TB SIM-kort finns tillgängliga.

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *