代码之家  ›  专栏  ›  技术社区  ›  Alex Weinstein

比较Visual Studio中的双精度-一种标准的捕获方法?

c#
  •  2
  • Alex Weinstein  · 技术社区  · 14 年前

    即使是经验丰富的程序员有时也会这样编写C代码:

    double x = 2.5;
    double y = 3;
    if (x + 0.5 == 3) {
        // this will never be executed
    }
    

    基本上,由于计算机处理浮点运算的方式,两个双精度数(或浮点数)永远不能精确相等是常识。

    问题是,每个人都知道这一点,但是像这样的代码仍然到处都是。这很容易被忽视。

    问题:

    • 在您的开发组织中,您是如何处理这个问题的?
    • 如果有人在比较两个double/float,那么编译器是否应该检查我们是否都应该大声尖叫,让vs2010包含编译时警告?

    更新 :各位,谢谢你们的评论。我想澄清一下,我非常肯定地理解上面的代码是不正确的。是的,您永远不想==比较双精度数和浮点数。相反,您应该使用基于epsilon的比较。很明显。这里真正的问题是“你如何确定问题所在”,而不是“你如何解决技术问题”。

    5 回复  |  直到 6 年前
        1
  •  3
  •   Jon Skeet    14 年前

    浮点值当然 可以 彼此平等,在这种情况下,你总是给予他们 平等。你应该 几乎 永远不要用等号来比较平等,但是你需要理解为什么——以及为什么你所举的例子不合适。

    我不认为这是编译器必须警告的事情,但您可能想看看这是否是fxcop可以接受的事情。我看不到它在 warning list 但它可能在某个地方…

    就我个人而言,我有理由相信有能力的开发人员能够在代码评审中发现这一点,但这确实取决于您是否准备好了代码评审。它还依赖于您的开发人员知道何时使用 double 何时使用 decimal 这是我经常发现的事情,不是吗…

        2
  •  2
  •   Paul Creasey    14 年前
    static int _yes = 0;
    static int _no = 0;
    
    static void Main(string[] args)
    {
        for (int i = 0; i < 1000000; i++)
        {
            double x = 1;
            double y = 2;
            if (y - 1 == x)
            {
                _yes++;
            }
            else
            {
                _no++;
            }
        }
        Console.WriteLine("Yes: " + _yes);
        Console.WriteLine("No: " + _no);
        Console.Read();
    }
    

    产量

    是的:1000000

    不:0

        3
  •  2
  •   Andrew Lygin    14 年前

    在我们的组织中,我们有很多财务计算,我们不使用浮动和双精度来完成这些任务。我们使用十进制in .net、Java中的BigDeCuffic和MSSQL中的数字来避免舍入错误。

    本文描述了问题: What Every CS Should Know About floating-Point Arithmetic

        4
  •  1
  •   philsquared    14 年前

    如果fxcop或类似的(如jon所建议的)对你来说不合适的话,就用一种更严厉的方法。 可以 获取代码的副本-将float或double的所有实例替换为编写的类,该类与 System.Double 除了你超载 == operator 生成警告!

    我不知道这在实践中是否可行,因为我还没有尝试过-但如果您尝试过,请告诉我们:-)

        5
  •  0
  •   kristianp    12 年前

    莫诺河 Gendarme 是一个类似fxcop的工具。它在正确性类别下有一个名为AvoidFloatingPointeQualityRule的规则。您可以尝试在代码中查找此错误的实例。我没有使用它,但它应该分析常规的.NET DLL。同名的fxcop规则早就被删除了。