在计算小float
矩阵的逆时,我在Eigen库中遇到了一些奇怪的行为。我发现在静态和动态矩阵大小上使用相同数据之间存在意外差异。
更令人惊讶的是,与使用double
矩阵得到的结果相比,似乎只有动态版本才能提供令人满意的结果。
那我在这里错过了什么?这是否意味着我应该在所有情况下使用动态版本?它只是不对。
以下是使用Visual Studio 2012,Release,x64编译的代码示例。
#include <iostream>
#include <Eigen/Dense>
int main()
{
//some static size 4x3 matrix
Eigen::Matrix<float,4,3> m;
m <<
-166.863f, -172.49f, -172.49f,
107.422f, 101.71f, 107.422f,
708.306f, 706.599f, 708.029f,
1.0f, 1.0f, 1.0f ;
//same but dynamic size
Eigen::MatrixXf mx = m;
//first result
std::cout << (m.transpose()*m).inverse() << std::endl << std::endl ;
/*
0.00490293 0.000445721 -0.00533875
0.000445721 0.00502179 -0.0054378
-0.00533875 -0.0054378 0.0107567
*/
//second result, completely different from the first one
std::cout << (mx.transpose()*mx).inverse() << std::endl << std::endl ;
/*
0.0328157 0.00291519 -0.0356753
0.00287851 0.0337197 -0.036493
-0.0356387 -0.0365297 0.0720099
*/
//third result, same as the second one, only small differences due to better accuracy
std::cout << (m.transpose()*m).cast<double>().inverse() << std::endl << std::endl ;
/*
0.032961 0.00297425 -0.0358793
0.00297425 0.0337394 -0.0366082
-0.0358793 -0.0366082 0.0723284
*/
//the condition number of the inversed matrix is quite huge if that matters : 175918
Eigen::JacobiSVD<Eigen::MatrixXf> svdF(m.transpose()*m);
std::cout << svdF.singularValues()(0) / svdF.singularValues()(svdF.singularValues().size()-1) << std::endl;
}