Delphi记录辅助程序用于双精度浮点数。

4

情况

我写了一个用于二次方程的类,代码如下。你可以在这里找到完整的代码,但对于问题来说并不是非常相关。

type
 TArrayOfDouble = array of array of double;

type
 TEqSecGrado = class
  private
   //variables
   a, b, c: double;
   delta: double;
   solutions: TArrayOfDouble;
   solRealCount: integer;
   solImaginaryCount: integer;
   class var currentIstances: integer;
   class var totalIstances: integer;
   //methods
   function getDelta(const vala, valb, valc: double): double; overload;
  public
   constructor Create(const a, b, c: double);
   destructor Destroy; override;
   //methods
   function getDelta: double; overload;
   function getSolutions: TArrayOfDouble; virtual;
   //properties
   property valueOfA: double read a;
   property valueOfB: double read b;
   property valueOfC: double read c;
   property realSolutionsCount: integer read solRealCount;
   property imaginarySolutionsCount: integer read solImaginaryCount;
   class property currentEquationsCount: integer read currentIstances;
   class property totalEquationsCount: integer read totalIstances;
 end;

我打算创建一个名为TArrayOfDouble的新类型,用来存放我的方程解。在主窗体中,我按照以下方式使用这个类:

procedure TForm3.Button1Click(Sender: TObject);
var solver: TEqSecGrado;
    soluzioni: TArrayOfDouble;
begin

 //f(x) = 3x^2 - x - 2 -> [sol.1 = 1 | sol.2 = -0,666666666666667]
 solver := TEqSecGrado.Create(3,-1,-2);

 try
  soluzioni := solver.getSolutions; 
  //soluzioni[0][0] = 1; soluzioni[0][1] = 0; 
  //soluzioni[1][0] = -0,666666666666667; soluzioni[1][1] = 0; 
 finally
  solver.Free;
 end;

end;

现在我已经得到了soluzioni中的结果,可以输出它们了。(我使用了一个矩阵,因为我将实际解放在了第一个位置,这种情况下是1和-0.67,如果需要,第二个位置是虚数解)。


问题

当我输出解时,我想将它们转换成分数。我想做类似于soluzioni[a][b].toFraction的事情。所以我想使用双重记录助手。

type
 TSupport = record helper for Double
   function toFraction: string;
   function toString: string; //I have added this LATER
 end;

我有一个疑问,当我创建了TSupporttoFraction方法后,我可以调用soluzioni[0][0].toFraction,但是我无法调用soluzioni[i][0].toString。

为了解决我的问题,我决定添加了toString函数,这样一切就正常了。记录助手是否隐藏了所有其他方法?如果我删除记录助手,我是否仍然可以像以前一样使用toString方法?

我知道助手是一种扩展类而不使用继承的方式,但为什么我只能使用我在助手中声明过的方法呢?


你如何实现一个有意义的函数,将任意浮点数值转换为分数。如果你想要精确地进行转换,那么你总是会得到形如 k/2^n 的分数,其中 k 和 n 是整数。这真的是你想要的吗? - David Heffernan
我正在为我的大学数学考试做这个,有人建议我使用连分数。我只会给出一个近似结果。例如 sqrt(3)/3 将会被转化成一个分数,但是当然这两个值是不同的,而该分数仅是一个巨大的近似。 - Alberto Miola
当然 :) 我知道我们无法表示像那样的无理数。这是我正在研究的一个(非常有趣的)主题,在这门课上,我试图找到一个合理的方法来获得一个不错的近似值。 - Alberto Miola
不要介意无理数。您只能表示形式为k/2^m的精确数字。因此,您无法表示1/3或1/10这样非常简单的有理数。顺便问一下,是哪门课程在用Pascal编程教授数学?一定是应用数学课程吧。我个人预计会看到Python或类似的语言。 - David Heffernan
1
太好了,听起来很棒。尽情享受吧!我想念当数学学生的日子...... - David Heffernan
显示剩余3条评论
1个回答

7
类和记录帮助程序的一个限制是只能同时激活一个。Double的ToString方法实际上是由Delphi RTL提供的记录帮助程序实现的。一旦您将您的帮助程序附加到类型中,那么RTL帮助程序就不再有效。 文档说:
您可以为单个类型定义并关联多个辅助程序。但是,在任何特定位置的源代码中,只有零个或一个辅助程序适用。最近范围内定义的帮助程序将适用。类或记录助手范围是按正常的Delphi方式确定的(例如,在单位的使用子句中从右到左)。
这是一个长期存在的问题,Embarcadero自从引入了助手以来就已经知道。多年来他们没有解决这个问题,即使最好的意愿,我认为您应该假设他们永远不会解决这个问题。
所以,您有两个选择:
1.连接您自己的帮助程序,并接受RTL帮助程序的功能将无法使用。
2.通过其他方式实现您的功能而不是使用帮助程序。

好的,发生这种情况是因为编译器忽略了RTL助手,只关心最后实现的助手(在这种情况下是我的)。 - Alberto Miola
1
正确。我已经添加了一个文档链接和相关摘录。 - David Heffernan
4
FYI: 您可以同时激活多个CLASS帮助程序。 CLASS帮助程序支持继承,因此您实际上可以将YOUR类帮助程序定义为前一个帮助程序的扩展,例如_TStringsHelper = CLASS HELPER(VclHelpers.TStringsHelper) FOR TStrings_,那么VclHelpers.TStringsHelper和刚刚声明的当前UNIT的TStringsHelper都将可访问。不幸的是,RECORD帮助程序不支持继承,因此我找到的唯一扩展现有RECORD帮助程序的方法是重新实现帮助程序作为内联方法调用旧的帮助程序。 - HeartWare
@Heartware:如果你仔细阅读自己的解释,你会发现即使使用类助手,仍然只有一个“活动”的助手,只是你可以使用继承将其他助手的功能继承到那个“活动”的助手中。当然,前提是你所需的内容可以通过单继承实现。如果有两个(不相关的)助手,并且你希望引入另一个助手,则必须选择从哪个助手继承,因为你不能同时从两个助手继承,而且只能有一个是活动的。 - Deltics
@Deltics:我想这取决于你对“Active”的理解。两个CLASS助手中的方法是直接可访问的,因此在我的理解中是“Active”的。 - HeartWare
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接