6

Delphi6 または Delphi 2010 で、Currency (vtemp1,vtemp2) 型の 2 つの変数を宣言し、0.09 の値を入力します。変数の 1 つを ABS 関数で埋め込み、それを他の変数と比較します。コンパイラ ウォッチが abs(vtemp1) と vtemp2 に対して同じ値を示しているため、比較によって肯定的な結果が得られることが期待されます。奇妙なことに、if ステートメントが失敗します!!!

注: - この問題は、数値 0.09 を処理する場合にのみ発生します (他の近い値をいくつか試してみると、正常な結果が得られました) - 変数を通貨ではなく Double として宣言すると、問題はなくなります。

4

3 に答える 3

17

その理由は型変換だと思います。関数は結果をAbs()返すため、変数は にキャストされます。ドキュメントを見てください:realcurrencyreal

通貨は、通貨計算の丸め誤差を最小限に抑える固定小数点データ型です。Win32 プラットフォームでは、下位 4 桁が暗黙的に小数点以下を表す、スケーリングされた 64 ビット整数として格納されます。割り当てや式で他の実数型と混合すると、Currency 値は自動的に 10000 で除算または乗算されます。

したがって、通貨は固定で、実数は浮動小数点です。あなたの質問のサンプルコードは次のとおりです。

program Project3;
{$APPTYPE CONSOLE}

const VALUE = 0.09;
var a,b  : currency;
begin
    a := VALUE;
    b := VALUE;

    if a = Abs(b) then writeln('equal')
    else writeln('not equal', a - Abs(b));

    readln;
end.

型変換のため、等しくない結果を生成します。

コンパイラ ウォッチは abs(vtemp1) と vtemp2 の同じ値を明らかにします

を追加してからx : realを呼び出しx := abs(b);xウォッチ リストに追加し、それを選択して を押しEdit watch、次に [浮動小数点] を選択します。Xになり0.899...967ます。

価値だけ0.09がそのような結果を生み出すわけではありません。このコードを試して確認できます:

    for i := 0 to 10000 do begin
        a := a + 0.001;
        b := a;
        if a <> abs(b) then writeln('not equal', a);
    end;

したがって、通貨変数の絶対値が必要な場合は、それを実行してください。浮動小数点を使用しないでくださいabs():

    function Abs(x : Currency):Currency; inline;
    begin
        if x > 0 then result := x
        else result := -x;
    end;
于 2012-08-13T08:10:06.827 に答える
6

少し明確にします。float 値を比較すると、「問題」が発生します。

var
  A: Currency;

begin
  A:= 0.09;
  Assert(A = Abs(A));
end;

これはAbs(A)、float 値を返し、A = Abs(A)float 比較として実装されているためです。

通貨の値を比較すると再現できませんでした:

var
  A, B: Currency;
begin
  A:= 0.09;
  B:= Abs(A);
  Assert(A = B);
end;

しかし、2 番目のサンプルも潜在的なバグです。B:= Abs(A)内部的には、通貨 (int64) への丸めを伴う 10000 による浮動小数点除算/乗算であり、FPU 丸めモードに依存するためです。


QC レポート #107893を作成しました。それは開かれました。

于 2012-08-13T11:01:41.797 に答える
2

Delphi XE2 Abs関数が通貨型をオーバーロードしないという難しい方法を見つけました。

Delphi XE2 docwikiを参照してください。

これらは abs でサポートされている唯一のタイプです

  • function Abs(X: ): 実数; 過負荷;
  • function Abs(X: ): Int64; 過負荷;
  • function Abs(X: ): 整数; 過負荷;
于 2013-11-28T16:58:53.517 に答える