Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
443
Task/Long-primes/Pascal/long-primes.pas
Normal file
443
Task/Long-primes/Pascal/long-primes.pas
Normal file
|
|
@ -0,0 +1,443 @@
|
|||
program Periode;
|
||||
|
||||
{$IFDEF FPC}
|
||||
{$MODE Delphi}
|
||||
{$OPTIMIZATION ON}
|
||||
{$OPTIMIZATION Regvar}
|
||||
{$OPTIMIZATION Peephole}
|
||||
{$OPTIMIZATION cse}
|
||||
{$OPTIMIZATION asmcse}
|
||||
{$else}
|
||||
{$Apptype Console}
|
||||
{$ENDIF}
|
||||
|
||||
uses
|
||||
sysutils;
|
||||
|
||||
const
|
||||
cBASIS = 10;
|
||||
PRIMFELDOBERGRENZE = 6542;
|
||||
{Das sind alle Primzahlen bis 2^16}
|
||||
{Das reicht fuer al8le Primzahlen bis 2^32}
|
||||
TESTZAHL = 500; //429496709;//High(Cardinal) DIV cBasis;
|
||||
|
||||
type
|
||||
tPrimFeld = array[1..PRIMFELDOBERGRENZE] of Word;
|
||||
|
||||
tFaktorPotenz = record
|
||||
Faktor, Potenz: Cardinal;
|
||||
end;
|
||||
//2*3*5*7*11*13*17*19*23 *29 > Cardinal also maximal 9 Faktoren
|
||||
|
||||
tFaktorFeld = array[1..9] of TFaktorPotenz; //Cardinal
|
||||
// tFaktorFeld = array [1..15] of TFaktorPotenz;//QWord
|
||||
|
||||
tFaktorisieren = class(TObject)
|
||||
private
|
||||
fFakZahl: Cardinal;
|
||||
fFakBasis: Cardinal;
|
||||
fFakAnzahl: Cardinal;
|
||||
fAnzahlMoeglicherTeiler: Cardinal;
|
||||
fEulerPhi: Cardinal;
|
||||
fStartPeriode: Cardinal;
|
||||
fPeriodenLaenge: Cardinal;
|
||||
fTeiler: array of Cardinal;
|
||||
fFaktoren: tFaktorFeld;
|
||||
fBasFakt: tFaktorFeld;
|
||||
fPrimfeld: tPrimFeld;
|
||||
procedure PrimFeldAufbauen;
|
||||
procedure Fakteinfuegen(var Zahl: Cardinal; inFak: Cardinal);
|
||||
function BasisPeriodeExtrahieren(var inZahl: Cardinal): Cardinal;
|
||||
procedure NachkommaPeriode(var OutText: string);
|
||||
public
|
||||
constructor create; overload;
|
||||
function Prim(inZahl: Cardinal): Boolean;
|
||||
procedure AusgabeFaktorfeld(n: Cardinal);
|
||||
procedure Faktorisierung(inZahl: Cardinal);
|
||||
procedure TeilerErmitteln;
|
||||
procedure PeriodeErmitteln(inZahl: Cardinal);
|
||||
function BasExpMod(b, e, m: Cardinal): Cardinal;
|
||||
property EulerPhi: Cardinal read fEulerPhi;
|
||||
property PeriodenLaenge: Cardinal read fPeriodenLaenge;
|
||||
property StartPeriode: Cardinal read fStartPeriode;
|
||||
end;
|
||||
|
||||
constructor tFaktorisieren.create;
|
||||
begin
|
||||
inherited;
|
||||
PrimFeldAufbauen;
|
||||
|
||||
fFakZahl := 0;
|
||||
fFakBasis := cBASIS;
|
||||
Faktorisierung(fFakBasis);
|
||||
fBasFakt := fFaktoren;
|
||||
|
||||
fFakZahl := 0;
|
||||
fEulerPhi := 1;
|
||||
fPeriodenLaenge := 0;
|
||||
fFakZahl := 0;
|
||||
fFakAnzahl := 0;
|
||||
fAnzahlMoeglicherTeiler := 0;
|
||||
end;
|
||||
|
||||
function tFaktorisieren.Prim(inZahl: Cardinal): Boolean;
|
||||
{Testet auf PrimZahl}
|
||||
var
|
||||
Wurzel, pos: Cardinal;
|
||||
begin
|
||||
if fFakZahl = inZahl then
|
||||
begin
|
||||
result := (fAnzahlMoeglicherTeiler = 2);
|
||||
exit;
|
||||
end;
|
||||
result := false;
|
||||
if inZahl > 1 then
|
||||
begin
|
||||
result := true;
|
||||
pos := 1;
|
||||
Wurzel := trunc(sqrt(inZahl));
|
||||
while fPrimFeld[pos] <= Wurzel do
|
||||
begin
|
||||
if (inZahl mod fPrimFeld[pos]) = 0 then
|
||||
begin
|
||||
result := false;
|
||||
break;
|
||||
end;
|
||||
inc(pos);
|
||||
if pos > High(fPrimFeld) then
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure tFaktorisieren.PrimFeldAufbauen;
|
||||
{Baut die Liste der Primzahlen bis Obergrenze auf}
|
||||
const
|
||||
MAX = 65536;
|
||||
var
|
||||
TestaufPrim, Zaehler, delta: Cardinal;
|
||||
begin
|
||||
Zaehler := 1;
|
||||
fPrimFeld[Zaehler] := 2;
|
||||
inc(Zaehler);
|
||||
fPrimFeld[Zaehler] := 3;
|
||||
|
||||
delta := 2;
|
||||
TestaufPrim := 5;
|
||||
repeat
|
||||
if prim(TestaufPrim) then
|
||||
begin
|
||||
inc(Zaehler);
|
||||
fPrimFeld[Zaehler] := TestaufPrim;
|
||||
end;
|
||||
inc(TestaufPrim, delta);
|
||||
delta := 6 - delta; // 2,4,2,4,2,4,2,
|
||||
until (TestaufPrim >= MAX);
|
||||
|
||||
end; {PrimfeldAufbauen}
|
||||
|
||||
procedure tFaktorisieren.Fakteinfuegen(var Zahl: Cardinal; inFak: Cardinal);
|
||||
var
|
||||
i: Cardinal;
|
||||
begin
|
||||
inc(fFakAnzahl);
|
||||
with fFaktoren[fFakAnzahl] do
|
||||
begin
|
||||
fEulerPhi := fEulerPhi * (inFak - 1);
|
||||
Faktor := inFak;
|
||||
Potenz := 0;
|
||||
while (Zahl mod inFak) = 0 do
|
||||
begin
|
||||
Zahl := Zahl div inFak;
|
||||
inc(Potenz);
|
||||
end;
|
||||
for i := 2 to Potenz do
|
||||
fEulerPhi := fEulerPhi * inFak;
|
||||
end;
|
||||
fAnzahlMoeglicherTeiler := fAnzahlMoeglicherTeiler * (1 + fFaktoren[fFakAnzahl].Potenz);
|
||||
end;
|
||||
|
||||
procedure tFaktorisieren.Faktorisierung(inZahl: Cardinal);
|
||||
var
|
||||
j, og: longint;
|
||||
begin
|
||||
if fFakZahl = inZahl then
|
||||
exit;
|
||||
|
||||
fPeriodenLaenge := 0;
|
||||
fFakZahl := inZahl;
|
||||
fEulerPhi := 1;
|
||||
fFakAnzahl := 0;
|
||||
fAnzahlMoeglicherTeiler := 1;
|
||||
setlength(fTeiler, 0);
|
||||
|
||||
if inZahl < 2 then
|
||||
exit;
|
||||
og := round(sqrt(inZahl) + 1.0);
|
||||
{Suche Teiler von inZahl}
|
||||
for j := 1 to High(fPrimfeld) do
|
||||
begin
|
||||
if fPrimfeld[j] > og then
|
||||
Break;
|
||||
if (inZahl mod fPrimfeld[j]) = 0 then
|
||||
Fakteinfuegen(inZahl, fPrimfeld[j]);
|
||||
end;
|
||||
if inZahl > 1 then
|
||||
Fakteinfuegen(inZahl, inZahl);
|
||||
TeilerErmitteln;
|
||||
end; {Faktorisierung}
|
||||
|
||||
procedure tFaktorisieren.AusgabeFaktorfeld(n: Cardinal);
|
||||
var
|
||||
i: integer;
|
||||
begin
|
||||
if fFakZahl <> n then
|
||||
Faktorisierung(n);
|
||||
write(fAnzahlMoeglicherTeiler: 5, ' Faktoren ');
|
||||
|
||||
for i := 1 to fFakAnzahl - 1 do
|
||||
with fFaktoren[i] do
|
||||
if potenz > 1 then
|
||||
write(Faktor, '^', Potenz, '*')
|
||||
else
|
||||
write(Faktor, '*');
|
||||
with fFaktoren[fFakAnzahl] do
|
||||
if potenz > 1 then
|
||||
write(Faktor, '^', Potenz)
|
||||
else
|
||||
write(Faktor);
|
||||
|
||||
writeln(' Euler Phi: ', fEulerPhi: 12, PeriodenLaenge: 12);
|
||||
end;
|
||||
|
||||
procedure tFaktorisieren.TeilerErmitteln;
|
||||
var
|
||||
Position: Cardinal;
|
||||
i, j: Cardinal;
|
||||
|
||||
procedure FaktorAufbauen(Faktor: Cardinal; n: Cardinal);
|
||||
var
|
||||
i, Pot: Cardinal;
|
||||
begin
|
||||
Pot := 1;
|
||||
i := 0;
|
||||
repeat
|
||||
if n > Low(fFaktoren) then
|
||||
FaktorAufbauen(Pot * Faktor, n - 1)
|
||||
else
|
||||
begin
|
||||
FTeiler[Position] := Pot * Faktor;
|
||||
inc(Position);
|
||||
end;
|
||||
Pot := Pot * fFaktoren[n].Faktor;
|
||||
inc(i);
|
||||
until i > fFaktoren[n].Potenz;
|
||||
end;
|
||||
|
||||
begin
|
||||
Position := 0;
|
||||
setlength(FTeiler, fAnzahlMoeglicherTeiler);
|
||||
FaktorAufbauen(1, fFakAnzahl);
|
||||
//Sortieren
|
||||
for i := Low(fTeiler) to fAnzahlMoeglicherTeiler - 2 do
|
||||
begin
|
||||
j := i;
|
||||
while (j >= Low(fTeiler)) and (fTeiler[j] > fTeiler[j + 1]) do
|
||||
begin
|
||||
Position := fTeiler[j];
|
||||
fTeiler[j] := fTeiler[j + 1];
|
||||
fTeiler[j + 1] := Position;
|
||||
dec(j);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function tFaktorisieren.BasisPeriodeExtrahieren(var inZahl: Cardinal): Cardinal;
|
||||
var
|
||||
i, cnt, Teiler: Cardinal;
|
||||
begin
|
||||
cnt := 0;
|
||||
result := 0;
|
||||
for i := Low(fBasFakt) to High(fBasFakt) do
|
||||
begin
|
||||
with fBasFakt[i] do
|
||||
begin
|
||||
if Faktor = 0 then
|
||||
BREAK;
|
||||
Teiler := Faktor;
|
||||
for cnt := 2 to Potenz do
|
||||
Teiler := Teiler * Faktor;
|
||||
end;
|
||||
cnt := 0;
|
||||
while (inZahl <> 0) and (inZahl mod Teiler = 0) do
|
||||
begin
|
||||
inZahl := inZahl div Teiler;
|
||||
inc(cnt);
|
||||
end;
|
||||
if cnt > result then
|
||||
result := cnt;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure tFaktorisieren.PeriodeErmitteln(inZahl: Cardinal);
|
||||
var
|
||||
i, TempZahl, TempPhi, TempPer, TempBasPer: Cardinal;
|
||||
begin
|
||||
Faktorisierung(inZahl);
|
||||
TempZahl := inZahl;
|
||||
//Die Basis_Nicht_Periode ermitteln
|
||||
TempBasPer := BasisPeriodeExtrahieren(TempZahl);
|
||||
TempPer := 0;
|
||||
if TempZahl > 1 then
|
||||
begin
|
||||
Faktorisierung(TempZahl);
|
||||
TempPhi := fEulerPhi;
|
||||
if (TempPhi > 1) then
|
||||
begin
|
||||
Faktorisierung(TempPhi);
|
||||
i := 0;
|
||||
repeat
|
||||
TempPer := fTeiler[i];
|
||||
if BasExpMod(fFakBasis, TempPer, TempZahl) = 1 then
|
||||
Break;
|
||||
inc(i);
|
||||
until i >= Length(fTeiler);
|
||||
if i >= Length(fTeiler) then
|
||||
TempPer := inZahl - 1;
|
||||
end;
|
||||
end;
|
||||
|
||||
Faktorisierung(inZahl);
|
||||
fPeriodenlaenge := TempPer;
|
||||
fStartPeriode := TempBasPer;
|
||||
end;
|
||||
|
||||
procedure tFaktorisieren.NachkommaPeriode(var OutText: string);
|
||||
var
|
||||
i, limit: integer;
|
||||
Rest, Rest1, Divi, basis: Cardinal;
|
||||
pText: pChar;
|
||||
|
||||
procedure Ziffernfolge(Ende: longint);
|
||||
var
|
||||
j: longint;
|
||||
begin
|
||||
j := i - Ende;
|
||||
|
||||
while j < 0 do
|
||||
begin
|
||||
Rest := Rest * basis;
|
||||
Rest1 := Rest div Divi;
|
||||
Rest := Rest - Rest1 * Divi; //== Rest1 Mod Divi
|
||||
|
||||
pText^ := chr(Rest1 + Ord('0'));
|
||||
inc(pText);
|
||||
|
||||
inc(j);
|
||||
end;
|
||||
|
||||
i := Ende;
|
||||
end;
|
||||
|
||||
begin
|
||||
limit := fStartPeriode + fPeriodenlaenge;
|
||||
|
||||
setlength(OutText, limit + 2 + 2 + 5);
|
||||
OutText[1] := '0';
|
||||
OutText[2] := '.';
|
||||
pText := @OutText[3];
|
||||
|
||||
Rest := 1;
|
||||
Divi := fFakZahl;
|
||||
basis := fFakBasis;
|
||||
|
||||
i := 0;
|
||||
Ziffernfolge(fStartPeriode);
|
||||
if fPeriodenlaenge = 0 then
|
||||
begin
|
||||
setlength(OutText, fStartPeriode + 2);
|
||||
EXIT;
|
||||
end;
|
||||
|
||||
pText^ := '_';
|
||||
inc(pText);
|
||||
Ziffernfolge(limit);
|
||||
pText^ := '_';
|
||||
inc(pText);
|
||||
|
||||
Ziffernfolge(limit + 5);
|
||||
end;
|
||||
|
||||
type
|
||||
tZahl = integer;
|
||||
|
||||
tRestFeld = array[0..31] of integer;
|
||||
|
||||
var
|
||||
F: tFaktorisieren;
|
||||
|
||||
function tFaktorisieren.BasExpMod(b, e, m: Cardinal): Cardinal;
|
||||
begin
|
||||
Result := 1;
|
||||
if m = 0 then
|
||||
exit;
|
||||
Result := 1;
|
||||
while (e > 0) do
|
||||
begin
|
||||
if (e and 1) <> 0 then
|
||||
Result := (Result * int64(b)) mod m;
|
||||
b := (int64(b) * b) mod m;
|
||||
e := e shr 1;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure start;
|
||||
var
|
||||
Limit, Testzahl: Cardinal;
|
||||
longPrimCount: int64;
|
||||
t1, t0: TDateTime;
|
||||
begin
|
||||
|
||||
Limit := 500;
|
||||
Testzahl := 2;
|
||||
longPrimCount := 0;
|
||||
t0 := time;
|
||||
|
||||
repeat
|
||||
write(Limit: 8, ': ');
|
||||
repeat
|
||||
if F.Prim(Testzahl) then
|
||||
begin
|
||||
F.PeriodeErmitteln(Testzahl);
|
||||
if F.PeriodenLaenge = Testzahl - 1 then
|
||||
begin
|
||||
inc(longPrimCount);
|
||||
if Limit = 500 then
|
||||
write(Testzahl, ',');
|
||||
end
|
||||
end;
|
||||
inc(Testzahl);
|
||||
until Testzahl = Limit;
|
||||
inc(Limit, Limit);
|
||||
write(' .. count ', longPrimCount: 8, ' ');
|
||||
t1 := time;
|
||||
if (t1 - t0) > 1 / 864000 then
|
||||
write(FormatDateTime('HH:NN:SS.ZZZ', t1 - t0));
|
||||
writeln;
|
||||
until Limit > 10 * 1000 * 1000;
|
||||
|
||||
t1 := time;
|
||||
writeln;
|
||||
writeln('count of long primes ', longPrimCount);
|
||||
writeln('Benoetigte Zeit ', FormatDateTime('HH:NN:SS.ZZZ', t1 - t0));
|
||||
|
||||
end;
|
||||
|
||||
begin
|
||||
F := tFaktorisieren.create;
|
||||
writeln('Start');
|
||||
start;
|
||||
writeln('Fertig.');
|
||||
F.free;
|
||||
readln;
|
||||
end.
|
||||
Loading…
Add table
Add a link
Reference in a new issue