0

我有一种情况,使用 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。

4

2 回答 2

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。如此小的差异几乎总是由于我上面列出的原因。

于 2017-02-28T08:42:53.933 回答
0

更深入地说,我看到平方值的总和引入了差异,当我在一个唯一向量和 3 个向量中仅使用一个 tem 计算 squaredNorm 时,我发现总数并不相同。

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 引入了舍入差异。

无论如何感谢您的回答。

佩德罗

于 2017-02-28T11:57:18.697 回答