Reputation: 109
I have an assignment and it says:
You have been provided a working program named Prime.
It has one input which is a single integer.
When the “Find Prime Number” button is pushed, the nth prime number is identified.
For example:
if 4 is entered and the button is clicked, the response is “The 4th prime number is 7” is displayed. And if 9 is entered, the response is “The 9th prime number is 23” is displayed.
The program is 100% accurate, it correct locates the nth prime.
The problem comes in when you try to find larger prime number.
For example:
if 10000 is entered and the button is clicked, the response is “The 10000th prime number is 104729” is displayed. This is the correct answer; however, it took over 48 seconds on my i7 computer to find the solution. Imagine how long it would take to find the millionth prime number. Your task is analyze the problem to find a more efficient solution that would make the program more useful. First you must understand how the code provided works. There is an exercise at the end of this document. You will use it to run the code by hand. Once you understand how it works, analyze the problem of finding a prime number to make the program operate more efficiently. The reason why the program is slow for large numbers is because I preform a lot of unnecessary calculations. Not you must use your own code. You cannot use any prebuilt prime number routines, functions, or libraries; doing so will result in a zero for the assignment. Thinking about what really needs to be done is the way to solve this.
He says that the best way is to use arrays, but I don't know how to use arrays to solve this problem. He also says to keep division (mod) at a minimum as well as if statements.
Here is the code he provided for us:
Option Strict On
Public Class Form1
Private Sub PositionBox_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PositionBox.TextChanged
If IsNumeric(PositionBox.Text) Then
If Decimal.Parse(PositionBox.Text) >= 1 Then
FindPrimeBtn.Enabled = True
Else
FindPrimeBtn.Enabled = False
End If
Else
FindPrimeBtn.Enabled = False
End If
End Sub
Private Sub FindPrimeBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles FindPrimeBtn.Click
Dim FinalPosition As Long
Dim FinalPrime, Even As Long
Dim Number As Long = 2
Dim CurrentPosition As Long = 1
Dim elapsed As System.TimeSpan
Dim sw As Stopwatch = New Stopwatch()
sw.Start() 'starts the clock
Dim IsPrime As Boolean
FinalPosition = Long.Parse(PositionBox.Text)
Even = CurrentPosition Mod 2
While (CurrentPosition > 2 And Even <> 0)
IsPrime = True
End While
While (CurrentPosition <= FinalPosition)
IsPrime = True
For x = 2 To Number - 1
If Number Mod x = 0 Then
IsPrime = False
End If
Next
If IsPrime Then
FinalPrime = Number
CurrentPosition += 1
End If
Number += 1
End While
elapsed = sw.Elapsed() 'captures the elapsed time it took to compute the result
ResultLbl.Text = "The " + FinalPosition.ToString() + "th is " + FinalPrime.ToString()
ElapsedTimeLbl.Text = "Elapsed time is " + elapsed.ToString()
End Sub
End Class
Upvotes: 0
Views: 2295
Reputation: 9607
check out this article , specifically, where it says: effort can be reduced by selecting only prime numbers as candidate factors. Furthermore, the trial factors need go no further than \scriptstyle\sqrt{n} because, if n is divisible by some number p, then n = p × q and if q were smaller than p, n would have earlier been detected as being divisible by q or a prime factor of q.
I think he wants you to store the primes you find in an array and then iterate through the set of primes in the array instead of iterating through each or each odd number.
Not sure if he'll allow you to import system.math, where the square root function is, but that speeds it up. I suppose you could ask...
Anyways, I'm not using the stored array of found prime numbers, and didn't like all his variable names, but if it helps, I was working with this:
Option Strict On
Imports System.Math
Public Class Form1
Private Sub PositionBox_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PositionBox.TextChanged
If IsNumeric(PositionBox.Text) Then
If Decimal.Parse(PositionBox.Text) >= 1 Then
FindPrimeBtn.Enabled = True
Else
FindPrimeBtn.Enabled = False
End If
Else
FindPrimeBtn.Enabled = False
End If
End Sub
Private Sub FindPrimeBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles FindPrimeBtn.Click
Dim CurrentprimeSequence As Long = 1
Dim FinalprimeSequence As Long
Dim prime_possible As Double = 2
Dim foundPrime As Double
Dim test_div As Double
'Dim Even As Long
Dim elapsed As System.TimeSpan
Dim sw As Stopwatch = New Stopwatch()
sw.Start() 'starts the clock
Dim IsPrime As Boolean
FinalprimeSequence = Long.Parse(PositionBox.Text)
'Even = CurrentprimeSequence Mod 2
'While (CurrentprimeSequence > 2 And Even <> 0)
' IsPrime = True
'End While
FindPrimeBtn.Enabled = False
While (CurrentprimeSequence <= FinalprimeSequence)
IsPrime = True ' until proven false
test_div = 2
Do While IsPrime And (test_div <= Sqrt(prime_possible))
IsPrime = (prime_possible Mod test_div > 0)
test_div = test_div + 1 - CDbl(test_div > 2) ' skip odd numbers after 2
'If test_div = 2 Then
' test_div = test_div + 1
'Else
' test_div = test_div + 2
'End If
Loop
'For test_div = 2 To Sqrt(prime_possible) ' test if divisible by any number two to square root of candidate, skip even #s
' If prime_possible Mod test_div = 0 Then
' IsPrime = False
' Exit For ' or change to while isprime and (test_div < prime_possible)
' End If
'Next
If IsPrime Then
foundPrime = prime_possible
If CurrentprimeSequence Mod 100000 = 0 Then
Debug.Print(CStr(CurrentprimeSequence) + " " + CStr(foundPrime) + " " + sw.Elapsed().ToString)
End If
CurrentprimeSequence += 1
End If
prime_possible += 1
End While
elapsed = sw.Elapsed() 'captures the elapsed time it took to compute the result
ResultLbl.Text = "The " + FinalprimeSequence.ToString() + "th is " + foundPrime.ToString()
ElapsedTimeLbl.Text = "Elapsed time is " + elapsed.ToString()
FindPrimeBtn.Enabled = True
End Sub
End Class
on my PC, it found the millionth prime in about 28 seconds, but you can't really compare performance across machines.
Upvotes: 1