7

我正在比较 DUnit 中的一些货币值,但它在我的机器上根本不起作用(在其他机器上工作,但在我的机器上不起作用)。

一个例子:

CheckEquals(16.65, SomeCurrencyFieldValue);

提高:

expected: <16,65> but was: <16,65>

如果执行以下操作,则比较有效:

var
  Temp: Currency;
begin
  Temp := 16.65;
  CheckEquals(Temp, SomeCurrencyFieldValue);

问题是:为什么当我将值直接传递给 CheckEquals 方法时比较不起作用?

4

4 回答 4

5

这个问题与Currency值如何在运行时转换为Extended值与浮点文字如何Extended在编译时转换为值有关。如果两种情况下的转换不同,则传递给的值CheckEquals可能不相等。

值得在调试器的 CPU 窗口中检查任何一个值是否在准备函数调用的过程中通过中间Double值。Extended额外的转换会影响结果的确切值。

要考虑的另一件事是 16.65 不能完全表示为一个Extended值,但它可以完全表示为一个Currency值。虽然Currency被归类为浮点类型,但它实际上是定点缩放的 64 位整数。CheckEquals这可能是在考虑到这一点的情况下在 DUnit 中请求额外过载的理由。

于 2009-01-28T19:12:58.123 回答
2

我看到 Delphi 2007 dUnit 源中只有 CheckEquals() 用于扩展值。但是你可以使用这个:

procedure CheckEquals(expected, actual: extended; delta: extended;
  msg: string = ''); overload; virtual;

并为货币价值提供适当的增量。

于 2009-01-28T18:33:06.957 回答
1

我遇到了同样的问题。看起来有些 DLL 修改了 FPU(处理器)控制字。这解释了为什么错误并不总是发生。当添加一些使用除以前测试套件之外的其他单元的新测试时,它可能会突然出现。或者,如果软件更新安装了错误的 DLL。我在我的博客上写过:

我还发现 Delphi 包含一个 SafeLoadLibrary 函数,它可以恢复控制字。

这也解释了为什么原始问题提到该问题与机器有关。

于 2010-11-10T15:17:36.460 回答
-1

这是一个建议的解决方案:

procedure CheckEquals(expected, actual: double; Precision:integer; msg:string ='');overload;virtual;

...

procedure TAbstractTest.CheckEquals(expected, actual: double;
  Precision: integer; msg: string);
var
  I: Integer;
begin
  FCheckCalled := true;
  for I := 0 to Precision do begin
    Expected := Expected * 10;
    Actual := Actual * 10;
  end;
  if Round(Expected) <> Round(Actual) then
    FailNotEquals( IntToStr(Round(Expected)), IntToStr(Round(Actual)), msg, CallerAddr);
end;

我知道它的糟糕实现,但只是一个想法,我更喜欢“delta”,而且更容易使用。

在当前版本的 dunit 中,您可以使用

procedure CheckEquals(expected, actual: extended; delta: extended; msg: string = ''); overload; virtual;
CheckEquals(0.011,0.01,0.009,'will pass');
于 2013-07-16T15:51:38.343 回答