逗号初始化和构造函数C和Eigen

我在C中使用Eigen库,我试图找到矩阵的行列式.根据我如何初始化矩阵,我会得到不同的结果.

方法一:

MatrixXd a(3, 3);
for (int n = 0; n < 3; n++)
    for (int m = 0; m < 3; m++)
        a(n,m) = (double) (n + m*m + 2.5)/3;

cout << "Matrix a: " << endl;
cout << a << endl;
cout << "Determinat of matrix a is: " << a.determinant() << endl;

这部分代码打印出来

Matrix a:
0.8333333  1.166667  2.166667
1.166667       1.5       2.5
1.5  1.833333  2.833333
Determinat of matrix a is: -7.401487e-17

方法二:

MatrixXd b(3, 3);
b << 0.8333333, 1.166667, 2.166667,
    1.166667, 1.5, 2.5,
    1.5, 1.833333, 2.833333;

cout << b;
cout << endl << "Determinant of matrix b is: " << b.determinant();

打印

0.8333333  1.166667  2.166667
1.166667       1.5       2.5
1.5  1.833333  2.833333
Determinant of matrix b is: 2.333331e-07

方法I产生错误的结果,而方法II给出正确的答案.第一种情况出了什么问题? (我正在使用Visual Studio.)提前感谢!

解决方法:

您在此观察到的是计算中的舍入误差.让我这样解释一下:

对于计算机而言,一切都基于二进制数系统,即我们在日常生活中使用的基数10,而不是基数10,计算机用基数2计算,即只有数字0和1.

这不仅适用于整数,也适用于像0.83333这样的实数……
但就像无法写入0.83333的所有数字……,您的计算机无法存储此数字的二进制表示的每个最后一位数 – 因此它必须以某种方式舍入结果.

根据您的初始化方式(通过计算(n m * m 2.5)/ 3或通过读取逗号初始化中的值),结果可能在最后一位数字中略有不同,从而导致不同的结果.

您可以通过比较0.8333333和2.5 / 3来尝试这一点,这可能会返回false.如果您打印数字,您会得到相同的结果,但内部表示略有不同.

但是你应该注意到绝对误差本身很小(小于0.000001),所以你现在不需要担心它.
如果您想要精确的结果,切换到可以准确表示这些值的有理数字类型可能会有所帮助.

上一篇:c – 以特征类型为参数的函数的不明确返回类型


下一篇:常用库的安装与配置(Eigen, PCL, OpenNI, Boost)