尝试使用Eigen中的某些操作结果来初始化一个向量时,似乎根据使用的语法不同而产生不同的结果。例如,在我的机器上,以下代码结束处的断言失败:
const unsigned int n = 25;
Eigen::MatrixXd R = Eigen::MatrixXd::Random(n,n);
Eigen::VectorXd b = Eigen::VectorXd::Random(n);
Eigen::VectorXd x = Eigen::VectorXd::Zero(n);
Eigen::VectorXd y = Eigen::VectorXd::Zero(n);
y = R.triangularView<Eigen::Upper>().solve(b);
x << R.triangularView<Eigen::Upper>().solve(b);
assert((x-y).norm() < std::numeric_limits<double>::epsilon()*10E6);
我意识到可能存在舍入误差,但我认为,在我的理解中,对R.triangularView<Eigen::Upper>().solve(b)
进行的两次评估应该具有相同的精度误差,因此结果相同。只有在一个变量使用<<
初始化,而另一个变量使用operator=
时才会出现这种情况,如果两个变量都以相同的方式分配,则不会出现这种情况。
当不仅在上三角部分使用向后代换,而是在R.lu().solve(b)
两者上进行评估并比较结果时,差异要小得多,但仍然存在差异。为什么两个向量在几乎相同的确定性方式下被分配时会有所不同?
我在基于 x86-64 架构的 Arch Linux 和 Debian 上尝试了这段代码,使用了 Eigen 版本 3.4.0,使用 C++11、C++17、C++20,使用clang和gcc编译。
#include <eigen3/Eigen/Dense> #include <cassert>
,我使用的是Eigen 3.4.0。 - pfischx
和y
之间的差异在e-14的数量级上。范数大约为2e-12,断言通过是因为eps*10e6等于2e-9。更改c++版本不会影响结果。此外,执行x << y
产生了预期的0.0
差异。执行x = R.triangular...
也产生了0.0
,因此我可以确认插入与求解确实导致了差异。 - Matt