简体   繁体   中英

Prime Number Visual Basic

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM