An Object-Oriented Way of Prime Numbers


One way to make the program object-oriented is to turn the sieve function into a method that fills an array of prime numbers passed by reference. The CSieve class does this through the AllPrimes method. The code is very similar to the local sieve function. The problem with this kind of method is that you must calculate all the prime numbers before you can get the first one. But some clients can’t wait. Those quink scientists I mentioned earlier, for example, want a steady stream of numbers fed to them one at a time.


This is the classic trade-off you’ll come to know in COM design. The purpose of any server is to transfer data across boundaries. Often, setting up the transfer is the most expensive part. You can be more efficient by passing larger chunks of data. But the larger the chunk, the longer the client has to wait. In this exercise, you’ll be testing the extremes—all at once versus one at a time.
In real programs, you might want to compromise by transferring medium-sized chunks.


The trick in getting numbers one at a time is to break the sieve function—which seems like an integrated whole—into its parts. Here’s what sieve really does:
You can break these tasks into the following members, methods, and properties:
Here’s the code to implement these methods and properties:

Private af() As Boolean, iCur As Integer
Private iMaxPrime As Integer, cPrime As Integer

Private Sub Class_Initialize()
‘ Default size is largest integer
iMaxPrime = 32766
ReInitialize
End Sub

Sub ReInitialize()
ReDim af(0 To iMaxPrime)
iCur = 1: cPrime = 0
End Sub

Property Get NextPrime() As Integer
‘ Loop until you find a prime or overflow array
iCur = iCur + 1
On Error GoTo OverMaxPrime
Do While af(iCur)
iCur = iCur + 1
Loop
‘ Cancel multiples of this prime
Dim i As Long
For i = iCur + iCur To iMaxPrime Step iCur
af(i) = True
Next
‘ Count and return it
cPrime = cPrime + 1
NextPrime = iCur
OverMaxPrime: ‘ Array overflow comes here
End Property

Property Get MaxPrime() As Integer
MaxPrime = iMaxPrime
End Property

Property Let MaxPrime(iMaxPrimeA As Integer)
iMaxPrime = iMaxPrimeA
ReInitialize
End Property

Property Get Primes() As Integer
Primes = cPrime
End Property

As you can see, the NextPrime property does most of the work. It looks quite different from the Sieve function, but it does essentially the same thing. You might need to study both the Sieve function and the NextPrime property for a minute to see the connection.


The code that calls the class methods looks a little different from the code that calls the function.

Case estBasicLocalClass
‘ Basic local class
Dim sieveLocal As New CSieve
sieveLocal.MaxPrime = txtMaxPrime.Text
If chkAll = vbUnchecked Then
‘ Get one at a time
ms = timeGetTime()
For i = 1 To cIter
sieveLocal.ReInitialize
Do
iPrime = sieveLocal.NextPrime
If fDisplay And iPrime Then
lstOutput.AddItem iPrime
lstOutput.TopIndex = lstOutput.ListCount - 1
lstOutput.Refresh
End If
Loop Until iPrime = 0
Next
txtTime.Text = timeGetTime() - ms
txtPrimes.Text = sieveLocal.Primes
Else
‘ Get all at once
§

The code calling the AllPrimes method to get all the primes at once looks a lot like the functional version, so there’s no need to show it here.