Вычисление определителя не является стабильным. Лучший способ - использовать Gauss-Jordan с частичным поворотом, который вы можете легко легко здесь проработать.
Решение системы 2x2
Давайте решим систему (используйте c, f = 1, 0, затем c, f = 0, 1, чтобы получить обратное)
a * x + b * y = c
d * x + e * y = f
В псевдокоде это выглядит как
if a == 0 and d == 0 then "singular"
if abs(a) >= abs(d):
alpha <- d / a
beta <- e - b * alpha
if beta == 0 then "singular"
gamma <- f - c * alpha
y <- gamma / beta
x <- (c - b * y) / a
else
swap((a, b, c), (d, e, f))
restart
Это стабильнее, чем определитель + коматрица (beta
- определитель * некоторая константа, вычисленная устойчивым образом). Вы можете получить полный эквивалент поворота (т. Е. Потенциально поменять местами x и y, чтобы первое деление на a
было таким, чтобы a
было наибольшим числом по величине среди a, b, d, e), и это может быть более стабильным в некоторых обстоятельствах, но вышеописанный метод работал хорошо для меня.
Это эквивалентно выполнению декомпозиции LU (сохранить гамму, бета, a, b, c, если вы хотите сохранить эту декомпозицию LU).
Вычисление QR-разложения также может быть выполнено явно (и также очень стабильно при условии, что вы делаете это правильно), но это медленнее (и включает в себя получение квадратных корней). Выбор за вами.
Повышение точности
Если вам нужна лучшая точность (вышеописанный метод стабилен, но есть некоторая ошибка округления, пропорциональная отношению собственных значений), вы можете «решить для исправления».
Действительно, предположим, что вы решили A * x = b
для x
с помощью вышеуказанного метода. Теперь вы вычисляете A * x
и обнаруживаете, что оно не совсем равно b
, что есть небольшая ошибка:
A * x - b = db
Теперь, если вы решите для dx
в A * dx = db
, у вас будет
A * (x - dx) = b + db - db - ddb = b - ddb
, где ddb
- ошибка, вызванная численным решением A * dx = db
, которое обычно намного меньше, чем db
(поскольку db
намного меньше, чем b
).
Вы можете повторить описанную выше процедуру, но обычно требуется один шаг для восстановления полной точности станка.