本程序使用矩阵快速幂运算方式来提高运行速度,计算到第1亿个数都没有问题。
程序中使用了rvelthuis的Delphi BigNumbers,可到下面的地址下载:
GitHub - rvelthuis/DelphiBigNumbers: BigInteger and BigDecimal for Delphi
unit uMain;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
Vcl.StdCtrls, Vcl.ComCtrls;
type
TForm1 = class(TForm)
RichEditResult: TRichEdit;
ButtonCalc: TButton;
EditNum: TEdit;
EditTime: TEdit;
Label1: TLabel;
Label2: TLabel;
procedure ButtonCalcClick(Sender: TObject);
private
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses uMatrix2;
procedure TForm1.ButtonCalcClick(Sender: TObject);
var
M: TMatrix2;
Delta: TDateTime;
begin
EditTime.Text := '';
RichEditResult.Text := '';
Application.ProcessMessages;
M.Init(1,1,1,0);
Delta := Now();
M := M.Pow(StrToInt(EditNum.Text));
Delta := Now() - Delta;
EditTime.Text := FormatDateTime('n:s.zzz', Delta);
RichEditResult.Text := M.Value[1,2].ToString;
end;
end.
object Form1: TForm1
Left = 0
Top = 0
Caption = 'Form1'
ClientHeight = 582
ClientWidth = 960
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
Position = poScreenCenter
DesignSize = (
960
582)
PixelsPerInch = 96
TextHeight = 13
object Label1: TLabel
Left = 362
Top = 554
Width = 48
Height = 13
Caption = #35745#31639#32791#26102
end
object Label2: TLabel
Left = 720
Top = 555
Width = 43
Height = 13
Caption = #31532'N'#20010#25968
end
object RichEditResult: TRichEdit
Left = 8
Top = 8
Width = 944
Height = 532
Anchors = [akLeft, akTop, akRight, akBottom]
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
Lines.Strings = (
'')
ParentFont = False
ScrollBars = ssVertical
TabOrder = 0
Zoom = 100
end
object ButtonCalc: TButton
Left = 877
Top = 549
Width = 75
Height = 25
Anchors = [akRight, akBottom]
Caption = 'calc'
TabOrder = 1
OnClick = ButtonCalcClick
end
object EditNum: TEdit
Left = 768
Top = 551
Width = 89
Height = 21
Anchors = [akRight, akBottom]
TabOrder = 2
Text = '10'
end
object EditTime: TEdit
Left = 416
Top = 551
Width = 89
Height = 21
TabOrder = 3
end
end
unit uMatrix2;
interface
uses Vcl.Dialogs, System.SysUtils, Velthuis.BigIntegers;
type
BigInt = BigInteger;
TMatrix2 = record
Value: array[1..2, 1..2] of BigInt;
public
class operator Multiply(const A, B: TMatrix2): TMatrix2;
class operator Add(const A, B: TMatrix2): TMatrix2;
class operator Equal(const A, B: TMatrix2): Boolean;
class operator Implicit(const aValue: UInt64): TMatrix2;
function Pow(N: UInt64): TMatrix2;
function ToString: String;
procedure Init(const A, B, C, D: BigInt);
end;
implementation
function TMatrix2.Pow(N: UInt64): TMatrix2;
var
Base: TMatrix2;
begin
if N = 0 then
Result := 1
else if N = 1 then
Result := Self
else
begin
Result := 1;
Base := Self;
while N > 0 do
begin
if (N and 1) > 0 then
Result := Result * Base;
Base := Base * Base;
N := (N shr 1);
end;
end;
end;
class operator TMatrix2.Implicit(const aValue: UInt64): TMatrix2;
begin
Result.Value[1, 1] := aValue;
Result.Value[1, 2] := 0;
Result.Value[2, 1] := 0;
Result.Value[2, 2] := aValue;
end;
class operator TMatrix2.Equal(const A, B: TMatrix2): Boolean;
var
I, J: Integer;
begin
Result := True;
for I := 1 to 2 do
begin
for J := 1 to 2 do
begin
if A.Value[I, J] <> B.Value[I, J] then
begin
Result := False;
Exit;
end;
end;
end;
end;
class operator TMatrix2.Add(const A, B: TMatrix2): TMatrix2;
var
I, J: Integer;
begin
for I := 1 to 2 do
begin
for J := 1 to 2 do
begin
Result.Value[I, J] := A.Value[I, J] + B.Value[I, J];
end;
end;
end;
class operator TMatrix2.Multiply(const A, B: TMatrix2): TMatrix2;
var
I, J: Integer;
begin
for I := 1 to 2 do
begin
for J := 1 to 2 do
begin
Result.Value[I, J] := A.Value[I, 1] * B.Value[1, J] +
A.Value[I, 2] * B.Value[2, J]
end;
end;
end;
function TMatrix2.ToString: String;
begin
Result := Format('[[%s, %s], [%s, %s]]',
[Value[1, 1].ToString, Value[1, 2].ToString,
Value[2, 1].ToString, Value[2, 2].ToString]);
end;
procedure TMatrix2.Init(const A, B, C, D: BigInt);
begin
Value[1, 1] := A;
Value[1, 2] := B;
Value[2, 1] := C;
Value[2, 2] := D;
end;
end.