|
-
Jun 27th, 2010, 08:11 PM
#1
Thread Starter
Lively Member
Generate Primes over 100 Million
Hello, I salvaged the following piece of code from:
http://www.vbforums.com/showpost.php...65&postcount=8
This code works fine, but the problem comes when I need to get all the primes above 100 million. I am familar (at least a little bit) with the BigInteger class in .NET 4.0, but when I replace all the instances of "Integer" with "BigInteger" in the following code I get this error:
Value of type 'System.Collections.Generic.List(Of System.Numerics.BigInteger)' cannot be converted to 'System.Collections.Generic.List(Of Integer)'.
(The reason I need primes above 100 million is that I'm trying to work through some projects on www.projecteuler.net)
Anyone have some ideas on how to modify the code to work with BigIntegers, Thank you very much for your help. If you need more code examples please ask.
vb.net Code:
'Sieve of Eratosthenes 'http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes '1. Create a contiguous list of numbers from two to some highest number n. '2. Strike out from the list all multiples of two (4, 6, 8 etc.). '3. The list's next number that has not been struck out is a prime number. '4. Strike out from the list all multiples of the number you identified in the previous step. '5. Repeat steps 3 and 4 until you reach a number that is greater than the square root of n (the highest number in the list). '6. All the remaining numbers in the list are prime. Private Function Sieve_of_Eratosthenes(ByVal MaxNum As Integer) As List(Of Integer) 'tested to MaxNum = 10,000,000 - on 1.8Ghz Laptop it took 1.4 seconds Dim thePrimes As New List(Of Integer) Dim toNum As Integer = MaxNum, stpw As New Stopwatch If toNum > 1 Then 'the first prime is 2 stpw.Start() thePrimes.Capacity = toNum 'size the list Dim idx As Integer Dim stopAT As Integer = CInt(Math.Sqrt(toNum) + 1) '1. Create a contiguous list of numbers from two to some highest number n. '2. Strike out from the list all multiples of 2, 3, 5. For idx = 0 To toNum If idx > 5 Then If idx Mod 2 <> 0 _ AndAlso idx Mod 3 <> 0 _ AndAlso idx Mod 5 <> 0 Then thePrimes.Add(idx) Else thePrimes.Add(-1) Else thePrimes.Add(idx) End If Next 'mark 0,1 and 4 as non-prime thePrimes(0) = -1 thePrimes(1) = -1 thePrimes(4) = -1 Dim aPrime, startAT As Integer idx = 7 'starting at 7 check for primes and multiples Do '3. The list's next number that has not been struck out is a prime number. '4. Strike out from the list all multiples of the number you identified in the previous step. '5. Repeat steps 3 and 4 until you reach a number that is greater than the square root of n (the highest number in the list). If thePrimes(idx) <> -1 Then ' if equal to -1 the number is not a prime 'not equal to -1 the number is a prime aPrime = thePrimes(idx) 'get rid of multiples startAT = aPrime * aPrime For mltpl As Integer = startAT To thePrimes.Count - 1 Step aPrime If thePrimes(mltpl) <> -1 Then thePrimes(mltpl) = -1 Next End If idx += 2 'increment index Loop While idx < stopAT '6. All the remaining numbers in the list are prime. thePrimes = thePrimes.FindAll(Function(i As Integer) i <> -1) stpw.Stop() Debug.WriteLine(stpw.ElapsedMilliseconds) End If Return thePrimes End Function
And here is what I changed it to:
vb.net Code:
Private Function Sieve_of_Eratosthenes(ByVal MaxNum As BigInteger) As List(Of BigInteger) 'tested to MaxNum = 10,000,000 - on 1.8Ghz Laptop it took 1.4 seconds Dim thePrimes As New List(Of BigInteger) Dim toNum As BigInteger = MaxNum, stpw As New Stopwatch If toNum > 1 Then 'the first prime is 2 stpw.Start() thePrimes.Capacity = toNum 'size the list Dim idx As BigInteger Dim stopAT As BigInteger = Math.Sqrt(toNum) + 1 '1. Create a contiguous list of numbers from two to some highest number n. '2. Strike out from the list all multiples of 2, 3, 5. For idx = 0 To toNum If idx > 5 Then If idx Mod 2 <> 0 _ AndAlso idx Mod 3 <> 0 _ AndAlso idx Mod 5 <> 0 Then thePrimes.Add(idx) Else thePrimes.Add(-1) Else thePrimes.Add(idx) End If Next 'mark 0,1 and 4 as non-prime thePrimes(0) = -1 thePrimes(1) = -1 thePrimes(4) = -1 Dim aPrime, startAT As BigInteger idx = 7 'starting at 7 check for primes and multiples Do '3. The list's next number that has not been struck out is a prime number. '4. Strike out from the list all multiples of the number you identified in the previous step. '5. Repeat steps 3 and 4 until you reach a number that is greater than the square root of n (the highest number in the list). If thePrimes(idx) <> -1 Then ' if equal to -1 the number is not a prime 'not equal to -1 the number is a prime aPrime = thePrimes(idx) 'get rid of multiples startAT = aPrime * aPrime For mltpl As BigInteger = startAT To thePrimes.Count - 1 Step aPrime If thePrimes(mltpl) <> -1 Then thePrimes(mltpl) = -1 Next End If idx += 2 'increment index Loop While idx < stopAT '6. All the remaining numbers in the list are prime. thePrimes = thePrimes.FindAll(Function(i As BigInteger) i <> -1) stpw.Stop() Console.WriteLine(stpw.ElapsedMilliseconds & " milliseconds to generate primes") End If Return thePrimes End Function
Last edited by patplays852; Jun 27th, 2010 at 08:28 PM.
-
Jun 27th, 2010, 08:27 PM
#2
Hyperactive Member
Re: Generate Primes over 100 Million
did you also change the instances of "Integer" to "BigInteger" in line 9?
-
Jun 27th, 2010, 08:29 PM
#3
Thread Starter
Lively Member
Re: Generate Primes over 100 Million
yup, I also updated first post to show what I have (should have done it before but I didn't think of it)
(at the top I also have)
vb.net Code:
Imports System.Math
Imports System.Numerics
Here is a custom class I wrote before finding the above code, it works, but is way too slow.
vb.net Code:
Class Primes
Dim LargestNonPrime As ULong = 0 ' Will only generate primes below this number
Dim primes As New ArrayList ' Will hold all our primes
Dim currentprime As Long = -1 ' set to -1 so that you will return the first prime in the array (0) because you have to iterate the currentprime b4 you can return the value
Dim toRemove As New ArrayList ' will hold the numbers to remove from our primes array (holds non-primes)
Sub Generate(ByVal tempnum As ULong)
LargestNonPrime = tempnum
Dim sw As New Stopwatch 'If you want to benchmark, uncomment this and the next line
sw.Start()
For x As Integer = 0 To LargestNonPrime ' Creates an arraylist from 0 to the number you specify
primes.Add(x)
Next
For i As Integer = 2 To LargestNonPrime / 2
Dim x As BigInteger = BigInteger.Multiply(i, i) ' Replace with Dim x as ulong = i*i if you are not running .NET 4.0 (imports system.numerics is required)
While x <= LargestNonPrime
toRemove.Add(x) 'adds all numbers that are non-prime into an array for removal
x += i
End While
Next
primes.Remove(0) 'manually remove 0 and 1 from the array (IF you count 1 as a prime number, then comment out or remove the next line)
primes.Remove(1)
toRemove.Sort() 'sorts the array from smallest to largest (when adding items to the array we have a LOT of doubles (when i was testing all primes for 100,000 i had close to .5million items in this array.
'remove doubles from toRemove array
For i = toRemove.Count - 1 To 1 Step -1
If (toRemove(i).ToString() = toRemove(i - 1).ToString()) Then
toRemove.RemoveAt(i)
End If
Next
'next 3 lines were used for debugging purposes
'For x As Integer = 0 To toRemove.Count - 1
' Console.WriteLine(toRemove(x).ToString)
'Next
For i As Integer = 0 To toRemove.Count - 1
primes.Remove(CInt(toRemove(i).ToString)) 'removes all of the items in the remove array from the array of primes we have going (leaves only primes left)
'Console.WriteLine(toRemove.Count.ToString & " left to remove, removing " & toRemove(i).ToString) 'used for debugging purposes
Next
'rest of the subroutine used for debugging purposes
sw.stop()
Console.WriteLine("ran in: " & sw.ElapsedMilliseconds & " number of primes: " & primes.Count)
'For x As Integer = 0 To primes.Count - 1
' Console.WriteLine(primes(x).ToString)
'Next
End Sub
Sub Reset()
currentprime = -1 'resets our current prime to -1 (so when we call .NextPrime() it will return the first value in the array
End Sub
Function NumOfPrimes() As ULong
Return primes.Count ' returns the number of primes we have...
End Function
Function NextPrime() As ULong
currentprime += 1 'since we set currentprime = -1 at the beginning and in the .Reset() sub it will add 1 making it equal to 0 and thus return the first item in the array of primes
Return primes(currentprime)
End Function
End Class
Last edited by patplays852; Jun 27th, 2010 at 09:14 PM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|