运行之间的双重计算的轻微变化

时间:2012-03-26 18:52:01

标签: java unit-testing double

另一位开发人员给了我一个算法,该算法返回一系列包含字符串化双精度数的字符串。我正在构建针对这些字符串输出的单元测试。我运行单元测试的时间大约有80%都通过了。另外20%的时间在返回的字符串的双重部分中发生轻微变化。例如:

Expected: ((B,D),(C,A)); : 0.05766153477579324
Found:    ((B,D),(C,A)); : 0.05766153477579325

Expected: (B,(C,(A,D))); : 0.0017518688483315935
Found     (B,(C,(A,D))); : 0.001751868848331593

我知道双重计算可能不精确,但我从未听说过它们是变体。算法作者向我保证算法是确定性的。双重对待的方式是:

    for(Tree gt: geneTrees){
        double prob = probList.next();
        total += prob;
        result.append("\n" + gt.toString() + " : " + prob);
    }

我有点不知道如何解释这种变化是可能的。有什么想法吗?

2 个答案:

答案 0 :(得分:3)

基于您正在进行的总结,我怀疑这可能是由于双重添加不是很可交换或关联的问题 - 如果你添加两个略有不同的双打,你会得到不同的舍入错误顺序。

基本上只为你的单元测试添加一个小epsilon。

答案 1 :(得分:0)

I am at a bit of a loss explain how this variation is possible.

直到有一个cpu体系结构/ os /编程语言来“统治它们”这样的问题才会发生。如果你愿意的话,你可以尝试找到一些方法让数字与100万位小数位相提并论,但我认为这是浪费时间而且可能不会持久。

Any ideas?

选择一个精度,如果您的数字在该精度内失败,则只会失败。如果您只关心(或能够测量)直至第二位,则无需将数字计算到小数点后10位。

例如,你有这个......

Expected: ((B,D),(C,A)); : 0.05766153477579324
Found:    ((B,D),(C,A)); : 0.05766153477579325
                                             ^
                                             |
                                             |
                               If this was a 9...would it change the behavior
                               of whoever is using your calculation?

换句话说......

Double expected = 0.05......
Double actual = Double.parseDouble(valueFromFile);

// Instead of doing this....
if(!expected.equals(actual)) {
  // fail test..
}

// Do this (only substitute .0001 with whatever you think an acceptable number is
// based off of the precision possible of the measurement of your input)....
if(Math.Abs(expected - actual) > .0001) {
   // fail test...
}