I've written an algorithm that I believe to be correct for computing prime numbers up to n with the Sieve of Eratosthenes. Unfortunately, this program hangs on really large values of n (try 10 million). Here is what I've written...
Protected Function Eratosthenes(ByVal n As Integer) As String
Dim maxValue As Integer = Math.Sqrt(n)
Dim values As Generic.List(Of Integer) = New Generic.List(Of Integer)
Dim i As Integer
''//create list.
For i = 2 To n
values.Add(i)
Next
For i = 2 To maxValue
If values.Contains(i) Then
Dim k As Integer
For k = i + 1 To n
If values.Contains(k) Then
If (k Mod i) = 0 Then
values.Remove(k)
End If
End If
Next
End If
Next
Dim result As String = ""
For i = 0 To values.Count - 1
result = result & " " & values(i)
Next
Return result
End Function
How might I speed this algorithm up? Where are my bottlenecks?
Removing elements from a large list is slow.
Why not create an array of Booleans values instead and set a value to "True" when you know that it's non-prime?
When you've found a new prime, you don't need to go through all higher values, just multiple of that one, setting the array element to True.
You can keep a separate list for primes you've found so far, if you want to return them.
Here's a C# implementation which just prints them out as it goes. (In C# if I wanted to return the values I'd return IEnumerable<T>
and use an iterator block.)
using System;
public class ShowPrimes
{
static void Main(string[] args)
{
ShowPrimes(10000000);
}
static void ShowPrimes(int max)
{
bool[] composite = new bool[max+1];
int maxFactor = (int) Math.Sqrt(max);
for (int i=2; i <= maxFactor; i++)
{
if (composite[i])
{
continue;
}
Console.WriteLine("Found {0}", i);
// This is probably as quick as only
// multiplying by primes.
for (int multiples = i * i;
multiples <= max;
multiples += i)
{
composite[multiples] = true;
}
}
// Anything left is a prime, but not
// worth sieving
for (int i = maxFactor + 1; i <= max; i++)
{
if (composite[i])
{
continue;
}
Console.WriteLine("Found {0}", i);
}
}
}
I am not a VB guy, but I think:
values.Remove(k)
is a waste of time, just set the place to 0, then extract the prime numbers to another list or sort the same list and remove all zeros at once.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With