Я заметил, что, казалось бы, эквивалентный код в F # и С# не выполняет то же самое. F # медленнее на порядок. В качестве примера я предоставляю свой код, который генерирует простые числа /, дает nth простое число в F # и С#. Мой код F #:
let rec isprime x =
primes
|> Seq.takeWhile (fun i -> i*i <= x)
|> Seq.forall (fun i -> x%i <> 0)
and primes =
seq {
yield 2
yield! (Seq.unfold (fun i -> Some(i, i+2)) 3)
|> Seq.filter isprime
}
let n = 1000
let start = System.DateTime.Now
printfn "%d" (primes |> Seq.nth n)
let duration = System.DateTime.Now - start
printfn "Elapsed Time: "
System.Console.WriteLine duration
И С# выглядит так:
class Program
{
static bool isprime(int n)
{
foreach (int p in primes())
{
if (p * p > n)
return true;
if (n % p == 0)
return false;
}
return true;
}
static IEnumerable<int> primes()
{
yield return 2;
for (int i=3; ; i+=2)
{
if (isprime(i))
yield return i;
}
}
static void Main(string[] args)
{
int n = 1000;
var pr = primes().GetEnumerator();
DateTime start = DateTime.Now;
for (int count=0; count<n; count++)
{
pr.MoveNext();
}
Console.WriteLine(pr.Current);
DateTime end = DateTime.Now;
Console.WriteLine("Duration " + (end - start));
}
}
Когда я измеряю для разных n
, я получаю преимущество для С# не менее 7x следующим образом:
- n = 100: С# = 5milsec F # = 64milsec
- n = 1000: С# = 22milsec F # = 180milsec
- n = 5000: С# = 280milsec F # = 2.05sec
- n = 10000: С# = 960milsec F # = 6.95sec
Мои вопросы:
- Являются ли эти две программы эквивалентными?
- Если да, почему они не скомпилированы в один и тот же/эквивалентный CLI?
- Если нет, почему бы и нет?
- Как я могу/я могу улучшить генератор простых чисел F #, чтобы выполнить больше похожего на С#?
- Как правило, могу ли я (или почему я не могу) всегда имитировать код С# в F #, чтобы мой код F # выполнялся одинаково быстро?
Edit1: Я понял, что сам алгоритм может быть улучшен путем перемещения только через нечетные, а не простые числа в isprime, что делает его нерекурсивным, но это своего рода перпендикулярный вопрос на заданные вопросы:)