TL; DR: rozwlekły post, który jest mi próbuje bronić Python (mój język z wyboru) przeciwko C#. W tym przykładzie C# działa lepiej, ale nadal pobiera więcej linii kodu, aby wykonać tę samą pracę, ale ostateczną korzyścią z wydajności jest to, że C# jest ~ 5x szybsze niż podobne podejście w Pythonie, gdy jest poprawnie kodowane. W rezultacie powinieneś użyć języka, który Ci odpowiada.
Po uruchomieniu przykładu C# ukończenie pracy na moim komputerze zajęło około 3 sekund i dało mi wynik 232,792,560. Można go zoptymalizować za pomocą znanego faktu, że liczba może być podzielna tylko na liczby od 1 do 20, jeśli liczba jest wielokrotnością 20, a zatem nie trzeba zwiększać o 1, ale zamiast tego. sprawił, że kod został wykonany ~ 10 razy szybciej w zaledwie 353 milisekund.
Po uruchomieniu przykładu Pythona, zrezygnowałem z oczekiwania i próbowałem napisać własną wersję przy pomocy itertools, która nie odniosła większego sukcesu i trwała tak długo jak twój przykład. Potem trafiam na akceptowalną wersję itertools, jeśli weźmiemy pod uwagę, że tylko wielokrotności mojej największej liczby mogą być podzielne na wszystkie liczby od najmniejszej do największej. Jako taki, rafinowany Python (3.6) Kod jest tutaj z funkcją dekorator rozrządu, który drukuje liczbę sekund zajęło wykonanie:
import time
from itertools import count, filterfalse
def timer(func):
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
print(time.time() - start)
return res
return wrapper
@timer
def test(stop):
return next(filterfalse(lambda x: any(x%i for i in range(2, stop)), count(stop, stop)))
print("Test Function")
print(test(20))
# 11.526668787002563
# 232792560
to również przypomniał mi pytanie Niedawno miałem odpowiedzieć na CodeFights dla Najmniej częste używanie wielkiej funkcji wspólnego mianownika w Pythonie. Ten kod jest następujący:
import time
from fractions import gcd
from functools import reduce
def timer(func):
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
print(time.time() - start)
return res
return wrapper
@timer
def leastCommonDenominator(denominators):
return reduce(lambda a, b: a * b // gcd(a, b), denominators)
print("LCM Function")
print(leastCommonDenominator(range(1, 21)))
# 0.001001596450805664
# 232792560
Podobnie jak w większości zadań programistycznych, czasami najprostsze podejście nie zawsze jest najszybsze. Niestety, to naprawdę wystawało, gdy tym razem spróbowano w Pythonie. To powiedziawszy, piękno w Pythonie to prostota uzyskania wykonania wykonawczego, gdzie zajęło 10 linii C#, udało mi się zwrócić poprawną odpowiedź w (potencjalnie) jednoliniowym wyrażeniu lambda i 300 razy szybciej niż mój prosta optymalizacja na C#. Nie jestem specjalistą w C#, ale wdrożenie tego samego podejścia Oto kod użyłem i jego wynik (około 5x szybciej niż Python):
using System;
using System.Diagnostics;
namespace ConsoleApp1
{
class Program
{
public static void Main(string[] args)
{
Stopwatch t0 = new Stopwatch();
int maxNumber = 20;
long start;
t0.Start();
start = Orig(maxNumber);
t0.Stop();
Console.WriteLine("Original | {0:d}, {1:d}", maxNumber, start);
// Original | 20, 232792560
Console.WriteLine("Original | time elapsed = {0}.", t0.Elapsed);
// Original | time elapsed = 00:00:02.0585575
t0.Restart();
start = Test(maxNumber);
t0.Stop();
Console.WriteLine("Test | {0:d}, {1:d}", maxNumber, start);
// Test | 20, 232792560
Console.WriteLine("Test | time elapsed = {0}.", t0.Elapsed);
// Test | time elapsed = 00:00:00.0002763
Console.ReadLine();
}
public static long Orig(int maxNumber)
{
bool found = false;
long start = 0;
while (!found)
{
start += maxNumber;
found = true;
for (int i=2; i < 21; i++)
{
if (start % i != 0)
found = false;
}
}
return start;
}
public static long Test(int maxNumber)
{
long result = 1;
for (long i = 2; i <= maxNumber; i++)
{
result = (result * i)/GCD(result, i);
}
return result;
}
public static long GCD(long a, long b)
{
while (b != 0)
{
long c = b;
b = a % b;
a = c;
}
return a;
}
}
}
Dla większości zadań wyższego poziomu, jednak zazwyczaj zobaczyć Python robiąc wyjątkowo dobrze w porównaniu do implementacji .NET, chociaż nie mogę uzasadnić roszczeń w tym momencie, poza tym, że biblioteka Pytań Pythona dała mi tyle, co podwójny do potrójnego zwrot w wydajności w porównaniu do C# WebRequest napisanego w ten sam sposób . Było to również prawdą podczas pisania procesów Selenium, ponieważ mogłem odczytać elementy tekstowe w Pythonie w ciągu 100 milisekund lub mniej, ale każde pobranie elementu zajęło C#> 1 sekundę, aby powrócić. Powiedziałem, że tak naprawdę wolę implementację C# ze względu na podejście obiektowe, w którym implementacja Selenium w języku Python jest funkcjonalna, co czasami jest bardzo trudne do odczytania.
Powinieneś użyć 'StopWatch' zamiast' DateTime' do obliczenia czasów wykonania w C# – juharr
I 'timeit' dla Pythona. – jonrsharpe
W odpowiedzi na komentarz @ juharr: W C# prawie nie stoję przy stole. Z drugiej strony z łatwością wypijam filiżankę kawy na dole, gdy Python się iteruje. – ssd