TL; DR: Скучный пост, который я пытаюсь защитить Python (мой язык по выбору) против C#. В этом примере C# работает лучше, но все же занимает больше строк кода для выполнения того же объема работы, но конечная производительность - это то, что C# в 5 раз быстрее, чем аналогичный подход в Python при правильной кодировке. Конечным результатом является то, что вы должны использовать язык, который вам подходит.
Когда я запустил пример C#, на мою машину потребовалось около 3 секунд и дал мне результат 232,792,560. Он может быть оптимизирован с использованием известного факта, что вы можете иметь только число, делящееся цифрами от 1 до 20, если число кратно 20, и поэтому вам не нужно увеличивать на 1, а вместо 20. Эта единственная оптимизация заставил код выполнить ~ 10 раз быстрее всего за 353 миллисекунды.
Когда я запускаю пример Python, я отказался от ожидания и попытался написать свою собственную версию с помощью itertools, которая не имела большого успеха и продолжалась до тех пор, пока ваш пример. Затем я нахожу приемлемую версию itertools, если учесть, что только кратные моего наибольшего числа могут быть делятся на все числа от наименьшего до самого большого. Таким образом, рафинированное Python (3,6) код здесь с функцией декоратор синхронизации, который печатает количество секунд потребовалось выполнить:
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
Это также напомнило мне вопрос, который я недавно должен был ответить на CodeFights для Наименее распространенный множественный с использованием функции Greatest Common Denominator в Python. Этот код выглядит следующим образом:
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
Как и в большинстве задач программирования, иногда самый простой подход не всегда является самым быстрым. К сожалению, это действительно застряло при попытке в Python на этот раз. Тем не менее, красота в Python - это простота выполнения исполнительского исполнения, где потребовалось 10 строк C#, я смог вернуть правильный ответ в (потенциально) однострочном лямбда-выражении и в 300 раз быстрее, чем мой простая оптимизация на C#. Я не специалист в C#, но реализация такой же подход здесь код, который я использовал, и его результат (около 5 раз быстрее, чем 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;
}
}
}
Для большинства задач более высокого уровня, тем не менее, я обычно вижу Python делая исключительно хорошо по сравнению с реализацией .NET, хотя в настоящее время я не могу обосновать претензии, не говоря о том, что библиотека Python Requests дала мне столько же, сколько двойное возвращение в производительности по сравнению с C# WebRequest, написанным таким же образом , Это также верно при написании процессов Selenium, поскольку я мог читать текстовые элементы в Python за 100 миллисекунд или меньше, но для каждого извлечения элементов потребовалось C#> 1 секунда для возврата. Тем не менее, я на самом деле предпочитаю реализацию C# из-за своего объектно-ориентированного подхода, когда реализация Selenium от Python становится функциональной, что очень сложно читать порой.
Вы должны использовать 'StopWatch' вместо' DateTime' для вычисления времени выполнения в C# – juharr
и 'timeit' для Python. – jonrsharpe
В ответ на комментарий @ juharr: На C# я почти не сижу со стола. С другой стороны, я легко могу выпить чашку кофе на два этажа внизу, когда Python выполняет итерацию. – ssd