我有一种情况,使用Eigen3库,norm()不能提供正确的答案。 norm()应该只是矢量到广场的系数的平方根:
NORM= sqrt( v[1]*v[1] + v[2]*v[2] + .... + v[N]*v[N])
然而,以下函数以两种方式计算norm():使用Eigen3的norm()方法和手动。结果略有不同:
void mytest()
{
double mvec[3];
mvec[0] = -3226.9276456286984;
mvec[1] = 6153.3425006471571;
mvec[2] = 2548.5894934614853;
Vector3d v;
v(0) = mvec[0];
v(1) = mvec[1];
v(2) = mvec[2];
double normEigen = v.norm();
double normByHand = sqrt( v(0)*v(0) + v(1)*v(1) + v(2)*v(2));
double mdiff = abs((normEigen - normByHand));
std::cout.precision(17);
std::cout << "normEigen= " << normEigen << std::endl;
std::cout << "normByHand= " << normByHand << std::endl;
std::cout << "mdiff= " << mdiff << std::endl;
}
此功能的输出为:
normEigen= 7400.8103858007089
normByHand= 7400.8103858007107
mdiff= 1.8189894035e-12
从数字15开始他们是不同的,为什么?在哪里四舍五入?
提前致谢 PedroC。
答案 0 :(得分:1)
计算是使用浮点计算的计算。因此,操作的顺序以及诸如矢量化之类的事物可能导致(通常)稍微不同的结果(由于不同的舍入,不同的数量级等)。 在这种情况下,差异仅在第15位。 64位浮点数的最大精度大约是第16位。
如果我们使用boost来查看ULP中的距离:
#include <boost/math/special_functions/next.hpp>
#include <iostream>
int main()
{
double normEigen = 7400.8103858007089;
double normByHand = 7400.8103858007107;
std::cout << boost::math::float_distance(normEigen, normByHand);
return 0;
}
我们看到距离(至少在我的系统上)是2.所以二进制数是例如 0101 ... 011而不是0101 ... 001。如此小的差异几乎总是由于我上面列出的原因。
答案 1 :(得分:0)
更深入我看到,当我在一个唯一向量中计算squaredNorm时,平方值的总和会引入差异 仅使用一个tem的3个向量我看到总数不相同。
void mytest2()
{
double mvec[3];
mvec[0] = -3226.9276456286984;
mvec[1] = 6153.3425006471571;
mvec[2] = 2548.5894934614853;
Vector3d v, v1, v2, v3;
v(0) = mvec[0];
v(1) = mvec[1];
v(2) = mvec[2];
v1(0) = mvec[0]; v1(1) = v1(2) = 0.0;
v2(0) = 0.0; v2(1) = mvec[1]; v2(2) = 0.0;
v3(0) = v3(1) = 0.0; v3(2) = mvec[2];
double squnorm = v.squaredNorm();
double squnorm1 = v1.squaredNorm();
double squnorm2 = v2.squaredNorm();
double squnorm3 = v3.squaredNorm();
double squnormbyhand = squnorm1 + squnorm2 + squnorm3;
double sqdiff = abs(squnorm - squnormbyhand);
std::cout.precision(17);
std::cout << "normEigen= " << squnorm << std::endl;
std::cout << "normByHand= " << squnormbyhand << std::endl;
std::cout << "mdiff= " << sqdiff << std::endl;
}
此功能的输出是:
normEigen= 54771994.366575643
normByHand= 54771994.366575658
mdiff= 1.49011161193847656e-8
由于某些原因,当添加平方值时,Eigen会引入舍入差异。
无论如何,谢谢你的回答。
佩德罗