【问题标题】:Comparing issues in DUnit CheckEquals with Currency Field Values将 DUnit CheckEquals 中的问题与货币字段值进行比较
【发布时间】:2009-01-28 18:27:52
【问题描述】:

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

一个例子:

CheckEquals(16.65, SomeCurrencyFieldValue);

加注:

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

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

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

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

【问题讨论】:

    标签: delphi dunit


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

        【解决方案3】:

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

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

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

        【讨论】:

          【解决方案4】:

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

          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');
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-09-19
            相关资源
            最近更新 更多