1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281:
| unit Mersennezahlengenerator;
{$IFDEF FPC} {$MODE Delphi} {$ENDIF}
interface
uses {$IFnDEF FPC} Windows, {$ELSE} LCLIntf, LCLType, LMessages, {$ENDIF} Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Menus, FileUtil;
const Dezimalen = 9; T = 1000 * 1000 * 1000; ExCo = 32; BG = (UInt64(1) shl ExCo); AusgabeDezi = 10; ZahlProZeile = 90 div (AusgabeDezi + 1); Max = 90000000;
type TFeld = array of LongWord;
TMersenneZahl = class(TForm) LabelExponent: TLabel; EditExponent: TEdit; LabelZiffernanzahl: TLabel; LabelZiffern: TLabel; LabelRechenzeit: TLabel; LabelSek: TLabel; LabelBereich: TLabel; LabelUeberSchrift: TLabel; OpenDialog: TOpenDialog; SaveDialog: TSaveDialog; MainMenu: TMainMenu; Datei: TMenuItem; Laden: TMenuItem; Speichern: TMenuItem; N1: TMenuItem; Beenden: TMenuItem; Berechnen: TMenuItem; Ausgabe: TMemo; procedure BerechnenClick(Sender: TObject); procedure BeendenClick(Sender: TObject); procedure SpeichernClick(Sender: TObject); procedure LadenClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure EditExponentKeyPress(Sender: TObject; var Key: char); private P: TFeld; Grenze, ZL,ZZ,Exponent: cardinal; Verzeichnis: string; procedure Ausgeben; public end;
var MersenneZahl: TMersenneZahl;
implementation
{$R *.dfm}
{$R-,Q-}
function TimeSekunden: extended; var H, M, S, MS: word; begin DecodeTime(Now, H, M, S, MS); TimeSekunden := 3600.0 * H + 60.0 * M + S + MS / 1000; end;
procedure TMersenneZahl.Ausgeben; var I, K, L: integer; Zeile, ZahlStr: string; slAusgabe: TStringList; begin slAusgabe := TStringList.Create;
ZahlStr := Format('%d', [P[ZL]]); for I := ZL - 1 downto 1 do ZahlStr := ZahlStr + Format('%.*d', [Dezimalen, P[I]]); L := length(ZahlStr); ZZ := L;
K := L mod AusgabeDezi; if k > 0 then begin K := AusgabeDezi - K; setlength(ZahlStr, L + K); Move(ZahlStr[1], ZahlStr[K + 1], L); fillchar(ZahlStr[1], K, '0'); end;
L := length(ZahlStr) div AusgabeDezi; K := 1; I := ZahlProZeile; Zeile := ''; repeat Zeile := Zeile + ' ' + copy(ZahlStr, K, AusgabeDezi); Inc(K, AusgabeDezi); Dec(i); if I <= 0 then begin slAusgabe.Add(Zeile); Zeile := ''; i := ZahlProZeile; end; Dec(L); until L <= 0;
if Zeile <> '' then slAusgabe.Add(Zeile);
Ausgabe.Lines.Assign(slAusgabe); slAusgabe.Free; end;
procedure TMersenneZahl.BerechnenClick(Sender: TObject); var Zeit:TDateTime; H,U : Uint64; pCar : ^LongWord; ExDiv,ExMod,K,L,IZ :Cardinal; begin LabelZiffern.Caption := '0'; LabelSek.Caption := '0.00 sek.'; Ausgabe.Lines.Clear; if EditExponent.Text = '' then EditExponent.Text := '521'; if StrToInt64(EditExponent.Text) > Grenze then begin MessageDlg('Der Exponent ist zu groß!', mtError, [mbRetry], 0); EditExponent.Text := '521'; exit; end; Screen.Cursor := crHourglass;
Exponent := StrToInt(EditExponent.Text);
ExDiv:=Exponent div ExCo; ExMod:=Exponent mod ExCo;
ZL:=trunc(Exponent*LN(2.0)/LN(T))+1; SetLength(P,0); SetLength(P,ZL+1);
P[1]:=1; IZ:=1; U:=0;
Zeit:=Time; for K:=ExDiv downto 1 do begin pCar := @P[1]; for L:=1 to IZ do begin H:=UInt64(pCar^) SHL ExCo +U; U:=H DIV T; pCar^:= H-U*T; inc(pCar); end; while U>0 do begin inc(IZ); H:=U; U:= U DIV T; pCar^:=H-U*T; inc(pCar); end; end;
for L:=1 to ZL do begin H:=UInt64(P[L]) SHL ExMod+U; U:=H DIV T; P[L]:=H-U*T end; Zeit:=Time-Zeit; Screen.Cursor := crDefault;
LabelSek.Caption := Format('%0.3f', [Zeit*86400]) + ' sek.'; Update; application.ProcessMessages; sleep(100);
P[1] := P[1] - 1;
ausgeben; LabelZiffern.Caption := IntToStr(ZZ); end;
procedure TMersenneZahl.BeendenClick(Sender: TObject); begin Close; end;
procedure TMersenneZahl.SpeichernClick(Sender: TObject); begin if ZL = 0 then begin MessageDlg('Du mußt erst eine Mersennezahl berechnen!', mtError, [mbOK], 0); exit; end; with SaveDialog do begin InitialDir := Verzeichnis; Filter := 'MersenneDateien (*.mrs) |*.mrs'; FileName := 'M' + IntToStr(Exponent); DefaultExt := 'mrs'; Options := [ofOverWritePrompt]; if Execute then begin Ausgabe.Lines.SaveToFile(FileName); MessageDlg(ExtractFileName(FileName) + ' ist gespeichert worden!', mtInformation, [mbOK], 0); end; end; end;
procedure TMersenneZahl.LadenClick(Sender: TObject); var I, K: integer; Zeile: string; T1: extended; begin with OpenDialog do begin InitialDir := Verzeichnis; Filter := 'MersenneDateien (*.mrs) |*.mrs'; FileName := ''; DefaultExt := 'mrs'; if Execute then begin Ausgabe.Lines.LoadFromFile(FileName); Zeile := ExtractFileName(FileName); Zeile := copy(Zeile, 2, Length(Zeile) - 5); EditExponent.Text := Zeile; Exponent := StrToInt(EditExponent.Text); ZL := trunc(Exponent * LN(2.0) / LN(T)) + 1; T1 := StrToFloat(copy(Ausgabe.Lines[0], 1, AusgabeDezi)); LabelZiffern.Caption := IntToStr(AusgabeDezi * ZL - AusgabeDezi+1 + trunc(LN(T1 + 1) / LN(10))); LabelSek.Caption := '0.00 sek.'; end else MessageDlg('Keine Datei geladen!', mtInformation, [mbOK], 0); end; end;
procedure TMersenneZahl.FormCreate(Sender: TObject); begin Grenze := trunc(Max * LN(T) / LN(2.0)); LabelBereich.Caption := '1 bis ' + IntToStr(Grenze); LabelZiffern.Caption := '0'; LabelSek.Caption := '0.00 sek.'; Verzeichnis := GetCurrentDirUTF8; end;
procedure TMersenneZahl.EditExponentKeyPress(Sender: TObject; var Key: char); begin if not (Key in ['0'..'9', #8]) then Key := #0; end;
end. |