Primzahlensuche
Zum Code
Hier haben wir ein optimiertes Projekt zur Suche von Primzahlen mit der Probedivision. Dabei werden alle ungeraden Zahlen ausgehend von 3 getestet, ob sie durch eine der bereits gefundenen Primzahlen teilbar sind. Es werden alle Primzahlen zwischen 2 und der Wurzel aus der zu testenden Primzahl geprüft.

Das Verfahren beruht auf der Überlegung, dass eine nicht-prime Zahl einen kleinen Primteiler besitzt. Wir nehmen an, a sei die zu testende nicht-prime Zahl, dann sei b der kleinste Teiler von a. b ist nun prim, da es keine Zahl c gibt, für die gilt 1 < c < b und die b teilt, i.e. gibt es keinen Teiler von b. Denn ein Teiler von b wäre auch ein Teiler von a, b ist aber der kleinste Teiler von a. Somit ist bewiesen, dass jede nicht-prime Zahl durch eine kleine Primzahl teilbar ist.

Um zu beweisen, dass eine Zahl prim ist, guckt man nun, ob man einen Primteiler zu dieser Zahl findet, der kleiner als die Wurzel aus ihr ist. Dadurch, dass wir nur Primzahlen für den Test verwenden und als frühzeitiges Abbruchkriterium die Wurzel der Zahl nehmen, ist diese Suche sehr schnell.

Ich habe bei dem Projekt alle Optimierungen des Compilers angeschaltet. So wird z.b. nicht mehr geprüft, ob beim Zugriff auf ein Array der Index existent ist, oder die Genauigkeit bei Fließkommaoperationen ist nun geringer als üblich. Dies ist möglich, da wir selbst dafür sorgen, dass wir keine Fehler erzeugen, die ohne diese Optionen von VB erkannt würden. Zudem rechnen wir stets mit ganzen Zahlen, wodurch auch die Fließkommaoperationen überflüssig sind.

Auf meinem Rechner benötigt er für 10.000 Primzahlen ca. 25 Millisekunden. Athlon XP2200+

Anmerkung: Die Klasse für die Geschwindigkeitsmessung stammt von ActiveVB.

History
25.01.2003 Hinzugefügt

Autor: Dominik Auras <Dominik_auf_vbinside.de>

Code aus Form1.frm
Public Function PrimzahlenSuche(count As Long) As Variant
Dim Primzahlen() As Long, p As Long, cnt As Long
Dim i As Long, ub_Prim As Long, ret As Long
Dim Wurzel As Long

'Wir suchen die ersten "count" Primzahlen
ReDim Primzahlen(count - 1)

Primzahlen(0) = 2
cnt = 1
ub_Prim = 0

p = 3
While cnt < count
Wurzel = Int(Sqr(p)) + 1
For i = 0 To ub_Prim
ret = p Mod Primzahlen(i)
If ret = 0 Then
Exit For
End If
If Primzahlen(i) > Wurzel Then
Exit For
End If
Next i

If ret <> 0 Then
ub_Prim = ub_Prim + 1
Primzahlen(ub_Prim) = p
cnt = cnt + 1
End If

p = p + 2
Wend

PrimzahlenSuche = Primzahlen
End Function

Public Function PrimzahlenSuche_Limit(limit As Long) As Variant
Dim Primzahlen() As Long, p As Long, cnt As Long
Dim i As Long, ub_Prim As Long, ret As Long
Dim Wurzel As Long

'Wir suchen alle Primzahlen die kleiner gleich "limit" sind
ReDim Primzahlen(100000)

Primzahlen(0) = 2
cnt = 1
ub_Prim = 0

p = 3
While p <= limit
Wurzel = Int(Sqr(p)) + 1
For i = 0 To ub_Prim
ret = p Mod Primzahlen(i)
If ret = 0 Then
Exit For
End If
If Primzahlen(i) > Wurzel Then
Exit For
End If
Next i

If ret <> 0 Then
ub_Prim = ub_Prim + 1

If UBound(Primzahlen) < ubprim Then
ReDim Preserve Primzahlen(UBound(Primzahlen) + 100000)
End If

Primzahlen(ub_Prim) = p
cnt = cnt + 1
End If

p = p + 2
Wend

ReDim Preserve Primzahlen(cnt - 1)

PrimzahlenSuche_Limit = Primzahlen
End Function

Private Sub Command1_Click()
Dim Primzahlen() As Long, i As Long, xTime As New xTimer

xTime.Calibrieren
xTime.Start
Primzahlen = PrimzahlenSuche(10000)
xTime.Halt

Label1.Caption = UBound(Primzahlen) + 1 & " Primzahlen " & _
Format(xTime.RunTime, "0.000000 ms")

List1.Clear
For i = 0 To UBound(Primzahlen)
List1.AddItem Primzahlen(i)
Next i
End Sub

Private Sub Command2_Click()
Dim Primzahlen() As Long, i As Long, xTime As New xTimer

xTime.Calibrieren
xTime.Start
Primzahlen = PrimzahlenSuche_Limit(10 ^ 6)
xTime.Halt

Label1.Caption = UBound(Primzahlen) + 1 & " Primzahlen " & _
Format(xTime.RunTime, "0.000000 ms")

List1.Clear
For i = 0 To UBound(Primzahlen)
List1.AddItem Primzahlen(i)
Next i
End Sub