0,0 → 1,172 |
// akPi v2.2 |
// Copyright (c) 1997-98 Anatoli Klassen |
|
unit CalcUnit; |
|
interface |
|
uses |
Classes, Graphics, ExtCtrls, ComCtrls, LongIntegerUnit, Dialogs; |
|
type |
TCalc = class(TThread) |
private |
FRes : PChar; |
FStatusBar : TStatusBar; |
FNDigit : longint; |
protected |
procedure ShowProgress(R : real); |
procedure Execute; override; |
public |
constructor Create(SB : TStatusBar; NDigit : longint; var Res : PChar); |
end; |
|
implementation |
|
uses SysUtils; |
|
procedure TCalc.ShowProgress(R : real); |
begin |
if R > 100 then R := 100; |
FStatusBar.SimpleText := Format('%5.1f%s', [R, '% Done']); |
end; |
|
procedure TCalc.Execute; |
const |
NewLine = #13#10' '; |
|
var |
Pi, X1, X2, X3 : PLongInteger; |
i, j, n, m, k1, k2 : longint; |
All : real; |
OldDecSeparator : char; |
|
begin |
OldDecSeparator := DecimalSeparator; |
DecimalSeparator := '.'; |
|
NumDWord := Round((FNDigit + 40) / 2.3) div 4; |
All := FNDigit * 1.47; |
k1 := 0; k2 := 0; |
|
GetMem(Pi, NumDWord * 4); |
GetMem(X1, NumDWord * 4); |
GetMem(X2, NumDWord * 4); |
GetMem(X3, NumDWord * 4); |
|
LetLong(X1^, 0); |
LetLong(X2^, 1); |
j := 0; |
for i := 1 to FNDigit do begin |
ShowProgress(i / All * 100); |
if i = 1 then DivLongLim(X2^, 5, j) |
else DivLongLim(X2^, 5*5, j); |
|
MovLongLim(X2^, X3^, j); |
DivLongLim(X3^, 2 * i - 1, j); |
while (NumDWord - j div 4 - 1 > 0) |
and (X2^[NumDWord - j div 4 - 1] = 0) do Inc(j, 4); |
if NumDWord - j div 4 - 1 <= 0 then Break; |
|
if i mod 2 = 1 then AddLongLim(X1^, X3^, j) |
else SubLongLim(X1^, X3^, j); |
|
if Terminated then begin |
FreeMem(Pi, NumDWord * 4); |
FreeMem(X1, NumDWord * 4); |
FreeMem(X2, NumDWord * 4); |
FreeMem(X3, NumDWord * 4); |
Exit; |
end; |
k1 := i; |
end; |
MovLong(X1^, Pi^); |
MulLong(Pi^, 16); |
|
LetLong(X1^, 0); |
LetLong(X2^, 1); |
j := 0; |
for i := 1 to FNDigit do begin |
ShowProgress((i + k1) / All * 100); |
if i = 1 then DivLongLim(X2^, 239, j) |
else DivLongLim(X2^, 239*239, j); |
|
MovLongLim(X2^, X3^, j); |
DivLongLim(X3^, 2 * i - 1, j); |
while (NumDWord - j div 4 - 1 > 0) |
and (X2^[NumDWord - j div 4 - 1] = 0) do Inc(j, 4); |
if NumDWord - j div 4 - 1 <= 0 then Break; |
|
if i mod 2 = 1 then AddLongLim(X1^, X3^, j) |
else SubLongLim(X1^, X3^, j); |
|
if Terminated then begin |
FreeMem(Pi, NumDWord * 4); |
FreeMem(X1, NumDWord * 4); |
FreeMem(X2, NumDWord * 4); |
FreeMem(X3, NumDWord * 4); |
Exit; |
end; |
k2 := i; |
end; |
MulLong(X1^, 4); |
SubLong(Pi^, X1^); |
|
i := NumDWord; |
while (i > 0) and (Pi^[i] = 0) do Dec(i); |
|
StrPCopy(FRes, IntToStr(Pi^[i]) + '.'); |
|
n := 0; |
m := 2; |
for j := FNDigit + i downto 1 do begin |
ShowProgress((n/2 + k1 + k2) / All * 100); |
if j <= 0 then Break; |
|
Pi^[i] := 0; |
MulLongLenLim(Pi^, 10, n div 3); |
Inc(n, 1); |
|
FRes[m] := Chr(Pi^[i] + Ord('0')); |
Inc(m); |
|
if n mod 50 = 0 then begin |
Move(NewLine, FRes[m], 5); |
Inc(m, 5); |
end |
else |
if n mod 10 = 0 then begin |
FRes[m] := ' '; |
Inc(m); |
end; |
|
if (n + 2) > FNDigit then Break; |
|
if Terminated then begin |
FreeMem(Pi, NumDWord * 4); |
FreeMem(X1, NumDWord * 4); |
FreeMem(X2, NumDWord * 4); |
FreeMem(X3, NumDWord * 4); |
Exit; |
end; |
end; |
FRes[m] := #0; |
|
FreeMem(Pi, NumDWord * 4); |
FreeMem(X1, NumDWord * 4); |
FreeMem(X2, NumDWord * 4); |
FreeMem(X3, NumDWord * 4); |
|
DecimalSeparator := OldDecSeparator; |
end; |
|
constructor TCalc.Create; |
begin |
FStatusBar := SB; |
FNDigit := NDigit + 1; |
FRes := Res; |
FreeOnTerminate := True; |
inherited Create(False); |
end; |
|
end. |