Dieser Algorithmus geht auf Michael Rabin und Gary Miller zurück, weshalb er ihren Namen trägt. Der Algorithmus, den ich hier verwendet habe, ist eine vereinfachte Version gegenüber derjenigen, die im DSS-Vorschlag empfohlen wird. Er ist sehr weit verbreitet, weil er so einfach ist.
Bevor man den Algorithmus anwenden kann muß man noch einige Vorbereitungen treffen:
Zuerst erzeugt man eine (möglichst große und ungerade) Zufallszahl p
Dann berechnet man die Zahl
Bestimme m so daß die folgende Gleichung erfüllt ist:
Nun kann der eigentlich Algorithmus auf
Falls aber
Die Wahrscheinlichkeit, daß eine nicht-Primzahl den Test trotzdem besteht beträgt 25%. Dabei nimmt aber diese Wahrscheinlichkeit schneller ab als bei den anderen zwei Algorithmen.
In meinem Programm habe ich Schritt 1 so geändert, daß

//Primzahltest nach Rabin-Miller
//Autor: Germanos Efthimiadis
//letzte Änderung: 13.1.1998
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#define MAXINT 32767
#define MAXLONGINT 4294967295l
#define SICHERHEIT 1000l //Anzahl der Tests mit verschiedenen a
//Autor: Bruce Schneier aus Angewandte Kryptographie S.285
//Funktion: mod
//Aufgabe: Berechnung der funktion modulo
//Parameter: unsigned long int a,x,n
//Rückgabe: unsigned long int (a^x mod n)
unsigned long int mod(unsigned long int a,unsigned long int x,unsigned long
int n)
{
unsigned long int s,t,u;
s=1;
t=a;
u=x;
while(u)
{
if(u&1)
s=(s*t)%n;
u>>=1;
t=(t*t)%n;
}
return(s);
}
//Autor: Germanos Efthimiadis
//Funktion: Zufall
//Aufgabe: Berechnung einer Zufallszahl<Obergrenze
//Paramater: unsigned long int i
//Rückgabe: unsigned long int (Zufallszahl)
unsigned long int Zufall(unsigned long int i)
{
unsigned long int x,x1,x2,x3;
x1=(unsigned long int)random(MAXINT);
x2=(unsigned long int)random(MAXINT);
x3=(unsigned long int)random(MAXINT);
x=x1*x2*x3;
x%=i; // x<i;
return(x);
}
//Autor: Germanos Efthimiadis
//Funktion: Hauptprogramm
//Aufgabe: Primzahltest nach Rabin-Miller
//Paramater: keine
//Rückgabe: keine
void main (void)
{
unsigned long int k,y,b,m,j,z
//In diesem Array werden alle a's gespeichert
//So wird verhindert, daß man mit demselbem a nochmal prüft
unsigned long int a[SICHERHEIT];
unsigned long int p;
int CursorY,CursorX; //Cursorkoordinaten
randomize(); //Initialisierung des Z-Generators
printf("\n\nEs wird eine ungerade Zufallszahl p erzeugt");
p=Zufall(MAXLONGINT);
if (p%2==0)
p--; //Ungerade Zahl
if (p<1000000000l)
p+=1000000000l; //10-stellige Zahl
printf("\np=%lu\n",p);
printf("\np wird jetzt %lu mal getestet\n",SICHERHEIT);
b=0; // Wie oft läßt sich p-1 ohne Rest teilen?
m=p-1;
while (m%2==0)
{
m/=2;
b++;
}; //m ergibt sich aus der Berechnung von b
CursorX=wherex();
CursorY=wherey();
for (k=0;k<SICHERHEIT;k++)
{
gotoxy(CursorX,CursorY);
printf("%lu. Test",k+1);
//Schritt 1
a[k]=Zufall(p-2);
y=0;
while (y<k)
{
if (a[k]==a[y]) //Gibt's die Zahl schon?
{
a[k]=Zufall(p-2); //Erzeuge neue Zahl
y=0; //Beginne Vergleich von vorne
} else
y++; //Setze Vergleich fort
}
//Schritt 2
j=0;
z=mod(a[k],m,p);
//Schritt 3
if (!(z==1 || z==p-1))
goto keine_primzahl;
//Schritt 4
schritt4:
if (j>0 && z==1)
goto keine_primzahl;
//Schritt 5
j++;
if (j<b && z!=p-1)
{
z=mod(z,2,p);
goto schritt4;
}
if (z!=p-1)
goto keine_primzahl;
//Schritt 6
if (j!=b || z==p-1)
{
printf("\n%lu ist eine Primzahl",p);
return;
}
keine_primzahl:
printf("\n%lu ist keine Primzahl",p);
return;
}