双重比较(再次)

时间:2014-09-25 16:14:49

标签: c++ double-precision

我有一个"黄金来源"算法完全准确,即输出精确到双精度。

我想比较另一种算法并确定它是否也准确到双精度。

例如,可能会输出以下三个数字:

A = 8.5534733167898555463e-05
X = 8.5534733167898640989e-05
Y = 8.553473316788089652e-05
sig:1 23456789012345

A是黄金来源。我可以看到A和X等于15位有效数字,而Y在第13位有效数字上有所不同。因此,Y不等于其他的精度,而A和X 可能等于双精度。

我看到this question,但我不确定如何应用它。如果我使用n = 1,它表示X相等,而Y不是,这似乎是合理的,但它是否正确?我希望它适用于n = 0,但这表明X和Y都是不相等的(也许这是正确的)。

2 个答案:

答案 0 :(得分:1)

双精度数字以尾数和指数形式存储在内部。 Equality checkin双精度浮点数是没有用的,因为它们可能非常接近甚至不完全相同。因此,您需要定义一个阈值。例如,您将epsilon定义为0.000000001左右(精度取决于您的精度容差)。然后,如果a,b是两个双数,则检查abs(a-b)< epsilon接受平等或几乎接近平等。

答案 1 :(得分:0)

我真的认为关键问题是:精确到双精度是什么意思?

我认为这有一个简单的答案:如果r是真正的答案,d是双重表示,那么d-r<=d'-r代表所有其他可能的双打,{{ 1}}。

这意味着如果我的2 nd 算法的输出等于来自黄金源的输出,或者实际解决方案恰好位于算法输出之间的一半,那么我的2 nd 算法只能精确到双精度。 / p>


我的2 nd 算法并不准确。

现在问题演变为:我需要什么准确度?我在与Debasish的交流中确立了绝对差异不是一个合适的指标。我怀疑相对差异更好,但不是我想要的。

我决定使用以下算法来报告&#34;差异&#34;,它认为15个有效数字的相等是相等的:

d'

最后,一些示例数据:

double doubles_differ(double a, double b) {
  const int significant_figures = 15;

  // This test will catch most cases
  if (std::abs(a - b) < pow(.1, significant_figures)
                        * std::max(std::abs(a), std::abs(b)))
    return 0;

  // Because we are at the edge of double precision, sometimes a case that is
  // actually equal slips through the above test. The following should be more
  // robust, but a lot slower.
  std::stringstream ss_a;
  std::stringstream ss_b;
  ss_a << std::setprecision(significant_figures - 1) << std::scientific << a;
  ss_b << std::setprecision(significant_figures - 1) << std::scientific << b;
  std::string s_a = ss_a.str();
  std::string s_b = ss_b.str();
  if (s_a == s_b)
    return 0;

  // Finally, return the difference scaled to unity.
  // Format: "7.70612131004268e-013" = significand, followed by "e±nnn".
  if (s_a.substr(s_a.length() - 5, 5) != s_b.substr(s_b.length() - 5, 5))
    throw std::runtime_error("Big diff");

  std::stringstream ss_convert_a(s_a.substr(0, s_a.length() - 6));
  std::stringstream ss_convert_b(s_b.substr(0, s_b.length() - 6));
  double a_converted;
  double b_converted;
  if (!(ss_convert_a >> a_converted))
    throw std::runtime_error("Could not convert a");
  if (!(ss_convert_b >> b_converted))
    throw std::runtime_error("Could not convert b");

  return std::abs(a_converted - b_converted);
}

请注意a = 9.9399367132570751e-016 b = 9.9399367132633209e-016 index 1 2345678901234567 diff = 6.3007377093526884e-012 relative diff = 6.2835472672107563e-013 上的指数表示有效数字的有效数字(在本例中为12)。我不确定相对差异表示什么(如果有的话)。

应该有更好的方法来做到这一点没有字符串...