我有一个"黄金来源"算法完全准确,即输出精确到双精度。
我想比较另一种算法并确定它是否也准确到双精度。
例如,可能会输出以下三个数字:
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都是不相等的(也许这是正确的)。
答案 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)。我不确定相对差异表示什么(如果有的话)。
应该有更好的方法来做到这一点没有字符串...