Hi, that is unrelated to the original post but as it is a comparison between C# and F# implementations of Sieve of Erastothenes I reasoned it will be better to post here than open a new thread.
So I was thinking of using some not so imperative techniques to implement the sieve on .NET. I came up with this for C# using LINQ:
class Program
{
public static List<int> Sieve(int max)
{
int[] numbers = new int[max - 1];
for (int i = 0; i < max - 1; i++)
{
numbers
= i + 2;
}
var ceiling = Math.Sqrt(max);
var primes = new List<int>();
while (numbers[0] <= ceiling)
{
primes.Add(numbers[0]);
numbers = (from r in numbers
where r % numbers[0] != 0
select r).ToArray();
//alternatively
//query = query.Where(i => i % first != 0).ToArray()
}
primes.AddRange(numbers);
return primes;
}
static void Main(string[] args)
{
foreach (int i in Sieve(120))
{
Console.WriteLine(i);
}
DateTime start = DateTime.Now;
Console.WriteLine(Sieve(10000000).Count);
Console.WriteLine("Time = " + DateTime.Now.Subtract(start).TotalMilliseconds);
}
}
As you can see I also timed it and the result on my machine was like 13 seconds for max value of 10000000
I came up with this implementation of F# (I am still a beginner in F# and I havent even got to use sequences yet but...):
let sieve max =
let ceiling = sqrt (float max) in
let rec sieveStep (numbers, currentPrimes) =
if float (List.hd numbers) > ceiling
then
(numbers, currentPrimes)
else
let newPrimes = currentPrimes @ [numbers.Head] in
sieveStep (List.filter (fun x -> x % numbers.Head <> 0) numbers, newPrimes) in
let (primesLeft, primes) = sieveStep ([2..max], []) in
primes @ primesLeft;;
let start = System.DateTime.Now;;
120 |> sieve |> List.iter (fun x -> printfn "%d" x);;
printfn "%f" (System.DateTime.Now.Subtract(start)).TotalMilliseconds;;
I also timed this and the result was more than 90 seconds.
So my question is what brings this performance difference. I perfectly understand that neither of this is the perfect implementation (I know you can do it with boolean array and use the indexes for the most efficient implementation). I perfectly understand that the two implementations are a lot different. Arrays vs linked lists, iteration vs recursion, etc. However what is the thing in the F# implementation that brings that huge performance penalty. I even instanciate new array objects for every iteration in the C# implementation so even object allocation in recursive implementation has somewhat of equivalent in C# code.
I also would like to know if these implementations are good enough and readable in both languages in your opinion and how can they be improved with functional constructs.
Thank you for your time