3

我正在使用 Borland Delphi7 进行一些 Pascal 编程。我已经下载了一个相当基本(免费)的复杂数学函数的源代码库,但不幸的是它没有附带任何使用示例。由于我对 Pascal 中的类不是很熟悉,我想我只需要一个简单的例子来说明它的用法就可以了。

任何事情都可以,即使是两个数字相加的例子也会让我开始。这是我尝试过的(我知道很蹩脚)。我认为我的问题是我不知道如何使用类构造函数。

uses ComplexMath in 'complexmath.pas'

var z1,z2,z3 : TComplexNumber;
begin
  z1.R:=1.0; z1.I:=2.0;
  z2.R:=3.0; z2.I:=-1.0;
  z3 := TComplexMath.Add(z1,z2);
end.

TComplexMath 的完整源代码可在此处获得:http ://delphi.about.com/library/weekly/aa070103a.htm 。我还剪切并粘贴了下面源代码的部分列表(请注意,此代码是完整的文件,除了我明确指出它已被剪切的地方)。

部分 TComplexMath 源代码清单是:

unit ComplexMath;

interface

uses Windows, SysUtils, Classes, Controls, Math;

type
  TComplexNumber = record
    R : single;
    I : single;
  end;

TComplexMath = class(TComponent)
  private
    { Private declarations }
  protected
    { Protected declarations }
  public
    { Public declarations }
    constructor Create(AOwner : TComponent); override;

    function Add(C1, C2 : TComplexNumber) : TComplexNumber; overload;
    { Returns the complex sum of C1 and C2 }

    function Add(C1, C2, C3 : TComplexNumber) : TComplexNumber; overload;
    { Returns the complex sum of C1 and C2 and C3 }

    ... and a bunch more like this ...

implementation

procedure Register;
  begin
    RegisterComponents('delphi.about.com', [TComplexMath]);
  end;

constructor TComplexMath.Create(AOwner : TComponent);
  begin
    inherited Create(AOwner);
  end;

 function TComplexMath.Add(C1, C2 : TComplexNumber) : TComplexNumber;
   begin
     Result.R := C1.R + C2.R;
     Result.I := C1.I + C2.I;
   end;

    ... and a bunch more like this ...

end.

经过一段时间的努力,我最终剥离了类定义,只使用了函数本身(就像一个简单的函数库)。尽管这对我有用,但我知道这不是该组件的用途。如果有人能向我展示一个按预期方式使用此类的非常简单的示例,我将不胜感激。

4

2 回答 2

7

我根本不会使用该代码。在我看来它真的很弱。这里有更好的:

type
  TComplex = record
  public
    class operator Implicit(const D: Double): TComplex;
    class operator Negative(const C: TComplex): TComplex;
    class operator Equal(const C1, C2: TComplex): Boolean;
    class operator NotEqual(const C1, C2: TComplex): Boolean;
    class operator Add(const C1, C2: TComplex): TComplex;
    class operator Add(const C: TComplex; const D: Double): TComplex;
    class operator Add(const D: Double; const C: TComplex): TComplex;
    class operator Subtract(const C1, C2: TComplex): TComplex;
    class operator Subtract(const C: TComplex; const D: Double): TComplex;
    class operator Subtract(const D: Double; const C: TComplex): TComplex;
    class operator Multiply(const C1, C2: TComplex): TComplex;
    class operator Multiply(const C: TComplex; const D: Double): TComplex;
    class operator Multiply(const D: Double; const C: TComplex): TComplex;
    class operator Divide(const C1, C2: TComplex): TComplex;
    class operator Divide(const C: TComplex; const D: Double): TComplex;
    class operator Divide(const D: Double; const C: TComplex): TComplex;
    function IsZero: Boolean;
    function IsNonZero: Boolean;
    function Conj: TComplex;
    function Sqr: TComplex;
    function Sqrt: TComplex;
    function Mag: Double;
    function SqrMag: Double;
  public
    r: Double;
    i: Double;
  end;

const
  ZeroComplex: TComplex = ();//initialise to zero;

class operator TComplex.Implicit(const D: Double): TComplex;
begin
  Result.r := D;
  Result.i := 0.0;
end;

class operator TComplex.Negative(const C: TComplex): TComplex;
begin
  Result.r := -C.r;
  Result.i := -C.i;
end;

class operator TComplex.Equal(const C1, C2: TComplex): Boolean;
begin
  Result := (C1.r=C2.r) and (C1.i=C2.i);
end;

class operator TComplex.NotEqual(const C1, C2: TComplex): Boolean;
begin
  Result := not (C1=C2);
end;

class operator TComplex.Add(const C1, C2: TComplex): TComplex;
begin
  Result.r := C1.r + C2.r;
  Result.i := C1.i + C2.i;
end;

class operator TComplex.Add(const C: TComplex; const D: Double): TComplex;
begin
  Result.r := C.r + D;
  Result.i := C.i;
end;

class operator TComplex.Add(const D: Double; const C: TComplex): TComplex;
begin
  Result.r := D + C.r;
  Result.i := C.i;
end;

class operator TComplex.Subtract(const C1, C2: TComplex): TComplex;
begin
  Result.r := C1.r - C2.r;
  Result.i := C1.i - C2.i;
end;

class operator TComplex.Subtract(const C: TComplex; const D: Double): TComplex;
begin
  Result.r := C.r - D;
  Result.i := C.i;
end;

class operator TComplex.Subtract(const D: Double; const C: TComplex): TComplex;
begin
  Result.r := D - C.r;
  Result.i := -C.i;
end;

class operator TComplex.Multiply(const C1, C2: TComplex): TComplex;
begin
  Result.r := C1.r*C2.r - C1.i*C2.i;
  Result.i := C1.r*C2.i + C1.i*C2.r;
end;

class operator TComplex.Multiply(const C: TComplex; const D: Double): TComplex;
begin
  Result.r := C.r*D;
  Result.i := C.i*D;
end;

class operator TComplex.Multiply(const D: Double; const C: TComplex): TComplex;
begin
  Result.r := D*C.r;
  Result.i := D*C.i;
end;

class operator TComplex.Divide(const C1, C2: TComplex): TComplex;
var
  R, Denominator: Double;
begin
  if abs(C2.r)>=abs(C2.i) then begin
    R := C2.i/C2.r;
    Denominator := C2.r+R*C2.i;
    Result.r := (C1.r+R*C1.i)/Denominator;
    Result.i := (C1.i-R*C1.r)/Denominator;
  end else begin
    R := C2.r/C2.i;
    Denominator := C2.i+R*C2.r;
    Result.r := (C1.r*R+C1.i)/Denominator;
    Result.i := (C1.i*R-C1.r)/Denominator;
  end;
end;

class operator TComplex.Divide(const C: TComplex; const D: Double): TComplex;
begin
  Result := C*(1.0/D);
end;

class operator TComplex.Divide(const D: Double; const C: TComplex): TComplex;
var
  R, Denominator: Double;
begin
  if abs(C.r)>=abs(C.i) then begin
    R := C.i/C.r;
    Denominator := C.r+R*C.i;
    Result.r := D/Denominator;
    Result.i := -R*Result.r;
  end else begin
    R := C.r/C.i;
    Denominator := C.i+R*C.r;
    Result.i := -D/Denominator;
    Result.r := -R*Result.i;
  end;
end;

function TComplex.IsZero: Boolean;
begin
  Result := Self=ZeroComplex;
end;

function TComplex.IsNonZero: Boolean;
begin
  Result := Self<>ZeroComplex;
end;

function TComplex.Conj: TComplex;
begin
  Result.r := r;
  Result.i := -i;
end;

function TComplex.Sqr: TComplex;
begin
  Result := Self*Self;
end;

function TComplex.Sqrt: TComplex;
var
  x, y, v, w: Double;
begin
  if IsZero then begin
    Result := ZeroComplex;
  end else begin
    x := abs(r);
    y := abs(i);
    if x>=y then begin
      v := y/x;
      w := System.Sqrt(x)*System.Sqrt(0.5*(1.0+System.Sqrt(1.0+v*v)));
    end else begin
      v := x/y;
      w := System.Sqrt(y)*System.Sqrt(0.5*(v+System.Sqrt(1.0+v*v)));
    end;
    if r>=0.0 then begin
      Result.r := w;
      Result.i := i/(2.0*w);
    end else begin
      if i>=0.0 then begin
        Result.i := w;
      end else begin
        Result.i := -w;
      end;
      Result.r := i/(2.0*Result.i);
    end;
  end;
end;

function TComplex.Mag: Double;
var
  x, y, Temp: Double;
begin
  x := abs(r);
  y := abs(i);
  if x=0.0 then begin
    Result := y;
  end else if y=0.0 then begin
    Result := x;
  end else if x>y then begin
    Temp := y/x;
    Result := x*System.Sqrt(1.0+Temp*Temp);
  end else begin
    Temp := x/y;
    Result := y*System.Sqrt(1.0+Temp*Temp);
  end;
end;

function TComplex.SqrMag: Double;
begin
  Result := System.Sqr(r) + System.Sqr(i);
end;

这使用运算符重载来实现+-和运算*/。您会发现您可以根据此TComplex记录编写的代码比您在问题中引用的组件更具表现力。

您链接到的代码中实现了更多功能。但是,很容易扩展此答案中的记录以添加更多功能。

当然,由于您拥有 Delphi 7,因此此答案中的代码对您没有帮助。那是因为直到后来才引入运算符重载。如果您要进行任何严肃的数学运算,则需要运算符重载以使代码可读。

于 2013-02-25T19:17:09.873 回答
7

预期的用法是这样的:

var
  cm: TComplexMath;

  z, w, sum: TComplexNumber;
begin

  cm := TComplexMath.Create(Self) // or nil, can most likely be anything
  try
    sum := cm.Add(z, w); // Now sum is the sum of z and w
  finally
    cm.Free;
  end;

end;

您还可以在应用程序启动(或单元初始化等)时创建一个实例,TComplexMath并在应用程序的整个生命周期中使用它:

unit Unit1;

interface

var
  cm: TComplexMath;

...

implementation

procedure Test;
begin

  sum := cm.Add(z, w); // Now sum is the sum of z and w

end;

...

initialization

  cm := TComplexMath.Create(nil);

finialization

  cm.Free;

最后,由于它是一个组件,因此您可以在设计时将其拖放到表单上。该实例将被调用ComplexMath1,您可以在表单类中使用它,例如

procedure TForm1.Button1Click(Sender: TObject);
var
  z, w, sum: TComplexNumber;    
begin
  sum := ComplexMath1.Add(z, w);
end;

真的不喜欢这门课的设计。首先,您只需要它的一个实例,那么为什么不将函数改为类函数呢?真的:为什么要使用一个类?最后,如果您使用现代版本的 Delphi,您可以使用高级记录和运算符重载来使诸如整数之类的东西z + w在您的源代码中工作,就像z简单类型一样!w

于 2013-02-25T19:03:40.593 回答