Выяснить влияние машинного эпсилона при решении собственных векторов вещественной матрицы 2 * 2 - PullRequest
0 голосов
/ 07 января 2019

Код поступает из функции eigen2x2 в opencv.

Для реальной матрицы со следующей формой:

image

решить для его собственных значений:

double u = (a + c)*0.5;
double v = std::sqrt((a - c)*(a - c)*0.25 + b*b);
double l1 = u + v; //the 1st eigenvalue
double l2 = u - v; // the 2nd eigenvalue

Затем найдите для собственных векторов, соответствующих l1, что означает решение для следующей системы:

image

Код в eigen2x2 выглядит следующим образом:

        double x = b;
        double y = l1 - a;
        double e = fabs(x);

        if (e + fabs(y) < 1e-4)
        {
            y = b;
            x = l1 - c;
            e = fabs(x);
            if (e + fabs(y) < 1e-4)
            {
                e = 1. / (e + fabs(y) + FLT_EPSILON);
                x *= e, y *= e;
            }
        }

        double d = 1. / std::sqrt(x*x + y*y + DBL_EPSILON);
        double x1 = x*d; //I moderately changed variable name for simplicity.
        double x2 = y*d;   

, где x1 и x2 составляют собственный вектор, соответствующий l1.

Вопрос

Насколько я понимаю, когда матрица приближается к нулевой матрице, будут выполняться следующие коды:

        e = 1. / (e + fabs(y) + FLT_EPSILON);
        x *= e, y *= e;

Так какую роль он играет? И допустимо ли выгнать FLT_EPSILON и последующие DBL_EPSILON?

1 Ответ

0 голосов
/ 07 января 2019

Они существуют для предотвращения деления на ноль (или по значениям ниже эпсилона). Вместо этого вы получаете большое число с плавающей точкой.

Если предположить, что ваши значения скромны по размеру, это почти не повлияет на результат; меньше, чем другие эффекты округления.

Безопасное удаление этого потребовало бы некоторого подмножества написания обширных модульных тестов, поиска документированных случаев, почему он был добавлен изначально, или широкого использования в большом разнообразном живом коде, где плохое поведение безопасно (нет денежной репутации или жизни на линии) все же заметно. Модульные тесты должны охватывать диапазон малых, нулевых, денормализованных значений, смешанных со средними и большими значениями, включая обратный инжиниринг белого ящика для получения указанных значений на каждом промежуточном этапе (чтобы быть безопасным).

Я бы оставил их там; они выглядят безвредными.

...