我在C ++中使用Eigen库,我试图找到矩阵的行列式。根据我如何初始化矩阵,我会得到不同的结果。
方法I:
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
方法II:
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。)提前致谢!
答案 0 :(得分:5)
您在此处观察到的是计算中的舍入错误。让我解释一下:
对于计算机而言,一切都基于二进制数系统,即我们在日常生活中使用的基数10,而不是基数10,计算机用基数2计算,即只有数字0和1。
这不仅适用于整数,也适用于像0.83333这样的实数... 但就像无法写入0.83333的所有数字...,您的计算机无法存储此数字的二进制表示的每个最后一位数 - 因此它必须以某种方式舍入结果。
根据您初始化的方式(通过计算(n + m*m + 2.5)/3
或通过读取逗号初始化中的值),结果可能会在最后一位数字中略有不同,从而导致不同的结果。< / p>
您可以通过将0.8333333与2.5 / 3进行比较来尝试这一点,这可能会返回false
。如果您打印数字,则会得到相同的结果,但内部表示略有不同。
但是你应该注意到绝对误差本身很小(小于0.000001),所以你现在不必担心它。 如果您想要精确的结果,切换到可以准确表示这些值的有理数字类型可能会有所帮助。