Двойное сравнение (снова)

У меня есть алгоритм «золотого источника», который является абсолютно точным, то есть вывод является точным с двойной точностью.

Я хочу сравнить другой алгоритм и определить, является ли он также точным с двойной точностью.

Например, могут быть выведены следующие три числа:

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

А это золотой источник. Я вижу, что A и X равны 15 значащим цифрам, а Y отличается 13-й значащей цифрой. Следовательно, Y не равен другим для удвоения точности, в то время как A и X может быть быть равным двойной точности.

Я видел этот вопрос, но я не уверен, как именно это применить. Если я использую n = 1, это означает, что X равен, а Y нет, что кажется разумным, но верно ли это? Я надеялся, что это сработает с n = 0, но это сигнализирует, что X и Y будут неравными (возможно, это правильно).

1

Решение

Числа двойной точности хранятся внутри в мантиссе и экспоненте. Проверка на равенство в числах с плавающей запятой двойной точности бесполезна, поскольку они могут быть очень-очень близкими, даже не совсем одинаковыми. Итак, вам нужно определить порог. Например, вы определяете эпсилон как, скажем, 0,000000001 или около того (точность зависит от вашего допуска точности). Затем, если a, b два двойных числа, проверьте, если abs (a-b) < эпсилон принять за равенство или почти за равенство.

1

Другие решения

Я действительно думаю, что ключевой вопрос: что значит быть точным с двойной точностью?

И я думаю, что есть простой ответ: если r это реальный ответ, и d является двойным представлением, то d-r<=d'-r для всех других возможных двойников, d',

Это означает, что мой 2й Алгоритм может быть точным с двойной точностью только в том случае, если его выходной сигнал равен выходному сигналу золотого источника или реальное решение находится точно на половине пути между выходными данными алгоритма.


Мой 2й Алгоритм не так точен.

Теперь возникает вопрос: какую точность мне требуется? Я установил в обмене с Debasish, что абсолютные различия не являются подходящей метрикой. Я подозреваю, что относительные различия лучше, но не совсем то, что я хочу.

Я остановился на следующем алгоритме, чтобы сообщить о «разнице», в которой равенство равняется 15 значащим цифрам:

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

Обратите внимание, что показатель степени на diff указывает количество значащих цифр точности (в данном случае 12). Я не уверен, что (если вообще что-то) указывает на относительную разницу.

Там должен быть лучший способ сделать это без строк …

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector