如何在矩阵求逆前检测其数值奇异性?
生成可逆随机方阵并求逆的问题
我需要实现一个算法:生成随机方阵,若矩阵数值奇异则重新生成,直到得到可逆矩阵后求逆。伪代码如下:
# 生成A while(A is numerically singular){ # 重新生成A } B = inv(A)
但我不知道如何正确编写A is numerically singular的判断条件。
我试过用matrixcalc::is.singular.matrix()函数,但matlib::inv是通过选主元判断奇异性,而这个函数是通过行列式判断,导致两者结果不一致。比如下面的例子:
library(matlib) library(matrixcalc) A <- matrix(c(10^9, 10^9-1, 1, 1), nrow=2, ncol=2) check <- is.singular.matrix(A) B <- matlib::inv(A)
此时check的值为FALSE,但matlib::inv会抛出错误:
Error in Inverse(X, tol = sqrt(.Machine$double.eps), ...) :
X is numerically singular
解决方案
既然matlib::inv内部是通过选主元结合容差判断奇异性,直接复用它的判断逻辑最可靠:
- 捕获逆运算的错误:尝试调用
matlib::inv,如果报错说明矩阵奇异,重新生成。示例代码:
library(matlib) generate_invertible_matrix <- function(n) { while(TRUE) { # 生成随机方阵,可根据需求调整生成方式(比如正态分布、均匀分布) A <- matrix(rnorm(n*n), nrow = n) tryCatch({ B <- inv(A) return(list(matrix = A, inverse = B)) }, error = function(e) { # 捕获奇异矩阵错误,继续循环生成新矩阵 if(grepl("numerically singular", e$message)) { next } else { # 其他错误直接抛出 stop(e) } }) } } # 使用示例 result <- generate_invertible_matrix(2) A <- result$matrix B <- result$inverse
- 直接调用
matlib::inv的底层判断逻辑:matlib::inv依赖Inverse函数,其判断奇异性的核心是检查LU分解中的主元是否小于容差tol = sqrt(.Machine$double.eps)。可以直接复用这个逻辑:
library(matlib) is_numerically_singular <- function(X, tol = sqrt(.Machine$double.eps)) { # 执行LU分解,复用matlib的判断逻辑 lu <- lu(X, tol = tol) any(lu$pivot == 0) } # 使用示例 n <- 2 while(TRUE) { A <- matrix(rnorm(n*n), nrow = n) if(!is_numerically_singular(A)) { break } } B <- inv(A)
这两种方式都能和matlib::inv的判断标准保持一致,避免出现“行列式非零但数值奇异”的矛盾情况。
内容的提问来源于stack exchange,提问作者Asigan
相关产品推荐
相关产品推荐

