java在两次运行之间的双重计算中略有变化
另一个开发人员给了我一个算法,它返回一系列包含字符串化双精度的字符串。我正在针对这些字符串输出构建单元测试。大约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);
}
我有点不知道如何解释这种变化是可能的。有什么想法吗
# 1 楼答案
仅仅根据你正在做的求和,我怀疑这可能是由于二重加法不是完全交换的或结合的,如果你以稍微不同的顺序加二重,你会得到不同的舍入误差
基本上,只需为单元测试添加一个小ε
# 2 楼答案
除非有一种cpu架构/操作系统/编程语言来“统领一切”,否则这样的问题就会发生。如果你愿意的话,你可以试着找到一些方法,把数字100%固定到小数点后百万位,但我认为这是浪费时间,而且很可能不会持续
选择一个精度,只有当你的数字在该精度范围内失败时,才失败一个差异。如果你只关心(或能够测量)到第二位的数字,就不需要计算到小数点后10位
例如,你有这个
换句话说