首页 > 解决方案 > 在求解 2*2 实矩阵的特征向量时阐明机器 epsilon 的影响

问题描述

代码来自opencv中的函数eigen2x2

对于具有以下形式的实矩阵:

求解其特征值:

double u = (a + c)*0.5;
double v = std::sqrt((a - c)*(a - c)*0.25 + b*b);
double l1 = u + v; //the 1st eigenvalue
double l2 = u - v; // the 2nd eigenvalue

然后求解对应于 的特征向量l1,这意味着求解以下系统:

中的代码eigen2x2如下:

        double x = b;
        double y = l1 - a;
        double e = fabs(x);

        if (e + fabs(y) < 1e-4)
        {
            y = b;
            x = l1 - c;
            e = fabs(x);
            if (e + fabs(y) < 1e-4)
            {
                e = 1. / (e + fabs(y) + FLT_EPSILON);
                x *= e, y *= e;
            }
        }

        double d = 1. / std::sqrt(x*x + y*y + DBL_EPSILON);
        double x1 = x*d; //I moderately changed variable name for simplicity.
        double x2 = y*d;   

其中x1x2构成对应于 的特征向量l1

问题

据我了解,当矩阵接近零矩阵时,将执行以下代码:

        e = 1. / (e + fabs(y) + FLT_EPSILON);
        x *= e, y *= e;

那么它的作用是什么呢?是否允许踢出FLT_EPSILON和后续DBL_EPSILON

标签: c++opencvprecisioneigenvectorepsilon

解决方案


它们的存在是为了防止除以零(或除以子 epsilon 值)。相反,你会得到一个很大的浮动。

假设您的值大小适中,它应该对结果几乎没有影响;小于其他舍入效果。

安全地删除它需要编写大量单元测试的一些子集,找到最初添加它的文档案例,或者在不良行为安全(没有金钱声誉或生命危险)但值得注意的各种实时代码中广泛使用。单元测试需要涵盖一系列小的、零、非规范化值以及中等和大的值,包括白盒逆向工程以在每个中间步骤生成所述值(为了安全起见)。

我会把它们留在里面;它们看起来无害。


推荐阅读