1

毎回、2 倍の itemCost (元は 0.80) を 0.20 ずつ減らす、この switch ステートメントがあります。0.00 に達したら、コードを実行したいと思います。0.00 になるまで問題なく動作しますが、itemCost は 0.00 ではなく 5.55111512312578E-17 になります。

switch ステートメントを実行するボタンを押したときの itemCost の出力値は次のとおりです。

0.60, 0.40, 0.20, 5.55111512312578E-17, -0.20, -0.40 etc

コード:

switch (codeString)
{
    case "20":
    {
        userAmount = userAmount + 0.20;
        itemCost = itemCost - 0.20;
        Console.WriteLine("" + itemCost);
        if (itemCost == 0.00)
        {
            giveChange();
            labelInstructions.Text = "giveChange";
        }
        else
        {
            string tempString = string.Format("{0:N2}", itemCost);
            labelInstructions.Text = "Please insert £" + tempString;
        }
        break;
    }
}

この奇妙な動作が発生する理由と修正方法を知っている人はいますか?

4

1 に答える 1

2

通貨を扱っているので、切り替えてDecimal データ型を使用する必要があります。

float と double は、0.0 に近づくにつれて加算と減算を処理するときに非常に奇妙な動作に遭遇します。

すべてのプラットフォームでプログラミングを行う場合、絶対精度が必要な場合は浮動小数点演算に十分注意することが重要です。たとえば、ゲーム開発者は 、グラフィックス カード、グラフィックス ライブラリ、およびパフォーマンスの制限により、浮動小数点の使用を余儀なくされています。通常、値がゼロかどうかを確認したい場合、ゼロと比較する代わりに、次のことを行います (疑似コード)

if AbsoluteValue(MyValue) < 0.001 then  //assume MyValue is zero.  

絶対に 10 進数に切り替えることができない場合は、同様のことができます。MyDouble が Epsilon of Zero 内にある場合 (Epsilon は 0.00001 付近の定数)、値を強制的にゼロにします。これは、シナリオの 99% では推奨されません。通貨には必ず Decimal を使用する必要があります。そうしないと、顧客に間違った金額を請求したり、一見ランダムなバグに見舞われたりすることになります。

于 2013-02-12T04:34:05.560 に答える