【问题标题】:Weird Behaviour using doubles [duplicate]使用双打的奇怪行为[重复]
【发布时间】:2013-01-27 08:05:07
【问题描述】:

我有这个 switch 语句,每次将 double itemCost(最初为 0.80)减少 0.20。当它达到 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;
    }
}

有谁知道为什么会出现这种奇怪的行为以及如何解决它?

【问题讨论】:

  • 你能在你忽略的循环中添加吗?这个开关只会运行一次。代码没有显示 itemCost 的原始值。
  • 您确定该值不是 5.557393938E-7 或末尾带有 E 的东西吗?
  • 十进制是适合货币的 .NET 类型。
  • 请在提问前搜索 SO。在关于 SO 的大约 450 万个问题中,可能有 10% 的问题涉及浮点数的不准确性 :-)

标签: c# .net-4.0 double switch-statement


【解决方案1】:

既然你在处理货币,你应该切换并使用Decimal datatype

当您接近 0.0 时,浮点数和双精度数在处理加法和减法时会遇到非常非常奇怪的行为。

在所有平台上进行编程时,当您需要绝对精度时,务必对浮点数学保持警惕,这一点至关重要。例如,游戏开发商是 由于显卡、图形库和性能限制,强制使用浮点数。通常,当他们想查看一个值是否为零时,而不是与零进行比较,他们会执行以下操作(伪代码)

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

如果你绝对不能切换到十进制,你可以做类似的事情。如果 MyDouble 在零的 Epsilon 内,其中 Epsilon 是 0.00001 附近的常量,则强制您的值为零。 99% 的情况下不建议这样做。你真的必须使用 Decimal 作为货币,否则你最终会向客户收取错误的金额或遭受看似随机的错误。

【讨论】:

  • 我会切换到十进制看看是否有帮助..
  • 我保证如果你所有的数学都是用小数完成的,它会解决这个问题。祝你好运!请注意,为了对小数进行硬编码,您可以在数字后面加上字母 D。MyDecimal = 0.2D
  • 例如,我已将所有内容更改为十进制 0.00M。现在我的 itemCost 输出变为 0.80、-0.20、-040、-0.60。
  • @Phil Hunter - 确保布尔表达式的两边都是小数。
  • 我的工作正常,就像一个魅力。我会将您标记为答案并为有用而给它+1。谢谢。
猜你喜欢
  • 1970-01-01
  • 2014-01-04
  • 2019-01-29
  • 1970-01-01
  • 2020-02-29
  • 1970-01-01
  • 1970-01-01
  • 2021-06-24
  • 2011-03-21
相关资源
最近更新 更多