2015-05-05 10 views
7

podczas eksperymentowania z Euler 99, zauważyłem, że te działania mają różny czas:wykładnicza kalkulacja w Pythonie

>>> 632382**518061 # never finishes.. 

>>> 632382**518061 > 519432**525806 # finishes in few seconds 
True 

Zastanawiam się, co jest tego powodem?

+1

Jako poboczny problem, gdy kompilator Pythona widzi '632382 ** 518061', myśli:" hej, prosta operacja na dwóch małych literałach całkowitych, zrobię to podczas kompilacji i ciągłego składania ". Tak więc, aby skompilować ten wiersz kodu, potrzeba około 3 sekund, ale tylko 20 nanosekund, aby go uruchomić (a następnie 200 sekund, aby sformatować ciąg do drukowania ...). Na Interaktywnym Interpremie, który nie ma znaczenia (chyba że spróbujesz porównać z 'timeit'), ale umieścisz go w module i' importuje 'ten moduł, i pierwszy raz zajmie 3 sekundy, ale jeśli zrobisz to ponownie (nawet po wyjściu i ponownym uruchomieniu) nie będzie. – abarnert

+1

Przy okazji, nawet bez problemu z odczytaniem 99, podejrzewam, że chodzi o to, aby podać liczby, które są zbyt duże, aby je obliczyć, więc musisz znać i/lub wyszukać i nauczyć się jakiegoś triku, takiego jak modułowa potęgowanie lub dzielenie się czynniki z każdej strony i tylko obliczania, gdy nie ma wspólnych czynników lub oszacowanie, a następnie testowanie, że błąd sięga. – abarnert

+0

Pamięć i czas są zagrożone, gdy próbuje wyświetlić liczbę z wieloma cyframi, jak widać w pierwszym przykładzie. W drugim nie ma potrzeby wyświetlania, tylko proste porównanie, które nie zużywa tyle czasu, co drukowanie na standardowe wyjście. –

Odpowiedz

12

Chodzi o to, że pyton próbuje wydrukować pierwszy wynik. Ale liczba ta ma cyfry miliardów, a python nie wypróżnia wyjścia, dopóki nie napotkany zostanie znak nowej linii, który następuje po wysłaniu wszystkich cyfr na standardowe wyjście. Jak wspomniał @abarnert, co jest wielokrotnie gorsze, to przekształcanie numeru w ciąg do drukowania. Wymaga to znacznej alokacji pamięci i mocy obliczeniowej. Z drugiej strony, drugie wyrażenie wystarczy wydrukować True. Możesz to sprawdzić, jeśli przypiszesz pierwsze wyrażenie:

>>> a = 632382**518061 

W ten sposób wyjście numeru jest pomijane.

+0

Myślę, że to bardziej formatowanie gigantycznego ciągu i drukowanie go na wyjściu. Na mojej maszynie potrzeba 1,68 s do kompilacji mnożenia, 24,6ns do oszacowania wynikowego skompilowanego literału, 28s do "str" ​​it, i tylko 2s do "zapisu" go. W systemie Windows pisanie może wymagać o wiele więcej czasu lub w trybie IDLE, ale przy prawidłowym standardzie nie powinno to być głównym wąskim gardłem. – abarnert

+0

To 28s jest dla Pythona 2.7, a 3.4 jest całkiem blisko, ale w 3.2, część 'str' zajmuje co najmniej 6 minut; Idę teraz do^C ... – abarnert

+0

@abarnert Ma sens, czy mogę dodać to w mojej odpowiedzi? – JuniorCompressor