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等しくない可能性があります。

関数呼び出しに備えて、Double途中で値のいずれかが中間値を通過するかどうか、デバッガーの CPU ウィンドウで確認する価値があります。Extended追加の変換は、結果の正確な値に影響します。

考慮すべきもう 1 つの点は、16.65 は値として正確に表現できるわけではありませんが、Extendedとして正確に表現できるというCurrencyことです。浮動小数点型に分類されますがCurrency、実際には固定小数点スケーリングされた 64 ビット整数です。CheckEqualsこれはおそらく、それを考慮して DUnit で追加のオーバーロードを要求する理由です。

于 2009-01-28T19:12:58.123 に答える
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;

私はその悪い実装を知っていますが、「デルタ」よりも好きで、はるかに使いやすいという単なるアイデアです。

現在のバージョンの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 に答える