【问题标题】:Comma initialization and Constructors C++ and Eigen逗号初始化和构造函数 C++ 和 Eigen
【发布时间】:2017-07-07 23:38:52
【问题描述】:

我在 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。)提前致谢!

【问题讨论】:

  • 手动尝试计算,我认为 0 是准确答案
  • 您必须以全精度打印浮点数才能进行此类实验,在您的情况下:cout &lt;&lt; setprecision(17) &lt;&lt; a &lt;&lt; endl;,将输出复制粘贴到方法 II(或任何其他工具),然后您将获得相同(或相当接近)的决定因素。

标签: c++ matrix eigen


【解决方案1】:

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

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

这不仅适用于整数,也适用于像 0.83333 这样的实数... 但是就像不可能写出 0.83333... 的所有数字一样,您的计算机也无法存储该数字的二进制表示的每个最后一个数字 - 因此它必须以某种方式对结果进行四舍五入。

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

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

但是您应该注意,绝对误差本身非常小(小于 0.000001),因此您目前无需担心。 如果您想要准确的结果,切换到可以准确表示这些值的有理数类型可能会有所帮助。

【讨论】:

    猜你喜欢
    • 2021-12-23
    • 1970-01-01
    • 2019-10-07
    • 2013-05-23
    • 2013-08-13
    • 1970-01-01
    • 2018-06-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多