Windows与Linux平台Eigen计算旋转矩阵结果不一致求解决
我在Windows(MSVC 2019 AMD 64)和Linux(Debian GCC 12.2.0)平台使用Eigen 3.3.7库计算旋转矩阵,运行完全相同的C++代码,但输出的旋转矩阵存在数值差异,希望实现两个平台运行结果一致。
测试代码
void testEigen() { Eigen::AngleAxisd xRot(0.0, Eigen::Vector3d::UnitX()); Eigen::AngleAxisd yRot(-M_PI/2, Eigen::Vector3d::UnitY()); Eigen::AngleAxisd zRot( M_PI/2, Eigen::Vector3d::UnitZ()); Eigen::Quaternion<double> q = xRot * yRot * zRot; auto _rotationMatrix = q.matrix(); // for (size_t i = 0; i < 3; i++) // { // for (size_t j = 0; j < 3; j++) // { // if (std::abs(_rotationMatrix(i, j)) < 1e-13) // { // _rotationMatrix(i, j) = 0.0; // } // if (std::abs((std::abs(_rotationMatrix(i, j)) - 1.0)) < 1e-13) // { // _rotationMatrix(i, j) = _rotationMatrix(i, j) < 0 ? -1.0 : 1.0; // } // } // } TRACE(4, "angle axisd x: " << std::defaultfloat << xRot.angle() << " y: " << yRot.angle() << " z: " << zRot.angle()); TRACE(4, "m_axis axisd x: " << xRot.axis() << " y: " << yRot.axis() << " z: " << zRot.axis()); TRACE(4, "Rotate matrix debug init _rotationMatrix 0: " << _rotationMatrix.row(0) << " 1: " << _rotationMatrix.row(1) << " 2: " << _rotationMatrix.row(2)); }
平台输出差异
Windows平台输出
angle axisd x: 0 y: -1.5707963267948965579989817342721 z: 1.5707963267948965579989817342721
m_axis axisd x: 1, 0, 0 y: 0, 1, 0 z: 0, 0, 1
Rotate matrix debug init _rotationMatrix
0: -4.4408920985006261616945266723633e-16 0 -1.0000000000000004440892098500626
1: 1.0000000000000004440892098500626 -4.4408920985006261616945266723633e-16 0
2: 0 -1.0000000000000004440892098500626 -4.4408920985006261616945266723633e-16
Linux平台输出
angle axisd x: 0 y: -1.5707963267948965579989817342721 z: 1.5707963267948965579989817342721
m_axis axisd x: 1, 0, 0 y: 0, 1, 0 z: 0, 0, 1
Rotate matrix debug init _rotationMatrix
0: 0 -2.2204460492503130808472633361816e-16 -1
1: 1 2.2204460492503130808472633361816e-16 0
2: 2.220446049250313080847263336181e-16 -1 2.2204460492503130808472633361816e-16
解决方案
- 启用数值修正逻辑:取消代码中注释的矩阵元素修正部分。这段代码会将绝对值小于1e-13的极小值置为0,将绝对值接近1的数修正为±1,能直接统一两个平台的输出结果。
- 统一浮点编译选项:
- MSVC:添加
/fp:precise和/Oi编译选项,确保浮点计算精度和优化行为一致。 - GCC:添加
-ffloat-store或-fp-model=precise选项,避免因寄存器缓存浮点值导致的计算差异。
- MSVC:添加
- 升级Eigen版本:Eigen 3.3.7是较旧的版本,后续稳定版(如3.4.x或3.5.x系列)修复了部分跨平台浮点计算一致性问题,升级后可能无需额外处理即可得到一致结果。
内容的提问来源于stack exchange,提问作者马昕悦

