W obliczu MemoryError w Pythonie

Napisałem program, aby znaleźć czynniki pierwsze liczby. Kiedy podam dużą liczbę (600851475143) jako dane wejściowe, pojawi się MemoryError. Poniżej znajduje się kod:

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] 

Z przeglądania dowiedziałem się, że Python korzysta z pamięci komputera – RAM. Używam Pythona w Unbuntu bez zmiany jego konfiguracji. Czy powinienem coś zmienić, aby działał na komputerze 64-bitowym. A może powinienem użyć dodatkowych funkcji, aby obejść ten błąd

Komentarze

  • Twoim podstawowym problemem jest to, że algorytm prawdopodobnie używa zbyt dużo pamięć. Jeśli używasz języka Python 2, range(1, a+1) próbuje utworzyć listę zawierającą 600851475143 elementów. Prawdopodobnie nie jest to to, czego chcesz, ponieważ każdy element będzie liczbą całkowitą, a każda liczba całkowita zajmuje 4 bajty. (Również to pytanie nie jest ' nie jest odpowiednie dla programistów, ponieważ naprawdę potrzebujesz przeglądu kodu i zrozumienia w szczególności, jak działa Python.)
  • (Prawdopodobnie chcesz xrange, który jest generatorem, który w razie potrzeby zwraca elementy do pętli for. To może nie być jedyny problem, który napotykasz. .)
  • Twoja lista ma 2,2 TB. Przełączenie na maszynę 64-bitową nie pomoże. Musisz zainstalować więcej niż 2 TB pamięci RAM (co, aby być uczciwym, będzie wymagało 64-bitowego systemu operacyjnego). Lub przemyśl swój algorytm.
  • Oprócz problemów z pamięcią (tylko dlatego, że nikt inny nie wskazał dotąd), istnieją bardziej wydajne algorytmy obliczania listy czynników liczby lub decydowania czy liczba jest liczbą pierwszą, czy też ma generować listę liczb pierwszych. Chociaż większość ludzi mówi o złożoności czasowej , istnieje również powiązana koncepcja złożoności przestrzeni .

Odpowiedź

Istnieje wiele sposobów mierzenia ilości pamięci używanej przez Twój program i możesz zwiększyć limity na użytkownika czy coś takiego.

Jednak nie musisz w pierwszej kolejności przydzielać tej pamięci, ponieważ możesz po prostu wygenerować sekwencję bez przechowywania jej wszystkich:

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) 

Pamiętaj, że możesz również iterować bezpośrednio po sekwencjach bez konieczności ich wielokrotnego indeksowania:

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

Komentarze

  • Lista w pytaniu ma 2,2 TB, wątpię, czy podniesienie limitów zasobów pomoże 😀
  • Cóż, może OP może poczekać do 2035 roku, kiedy Dostępnych jest 8 TB SIMMS.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *