You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何对Eigen::Array进行无序的逐行近似相等比较?

问题:验证Eigen数组行无序近似相等的简洁单元测试写法

我正在为一个输出4行2列Eigen::Array的函数写单元测试,需要验证实际输出和预期结果近似相等,但行的顺序不要求一致——也就是实际结果的每一行都要能匹配预期结果里的任意一行。目前用嵌套循环实现了验证,但觉得不够简洁,想利用Eigen的any()简化,试了一段代码但编译不通过,求更优实现方式。

现有测试代码

Eigen::Array<float, 4, 2> expectedResult {{-14.1421356F, -14.1421356F},
                                          {-28.2842712F, 28.2841712F},
                                          {14.1421356F, 14.1421356F},
                                          {28.2842712F, -28.284172F}};

Eigen::Array<float, 4, 2> result = myFunction();
for (int rowIndex = 0; rowIndex < 4; rowIndex++)
{
        // 检查result的每一行是否匹配expectedResult中的某一行,顺序无关
        // @todo 找更简洁的写法
        bool foundMatch = false;
        for (int comparisonRowIndex = 0; comparisonRowIndex < 4; comparisonRowIndex++)
        {
            if (result.row(rowIndex).isApprox(expectedResult.row(comparisonRowIndex), TOLERANCE))
            {
                foundMatch = true;
            }
        }
        EXPECT_TRUE(foundMatch);
}

尝试的错误代码

for (int rowIndex = 0; rowIndex < 4; rowIndex++)
{
    EXPECT_TRUE(expectedResult.rowwise().isApprox(result.row(rowIndex), TOLERANCE).any());  // 无法编译
}

错误原因

rowwise().isApprox()要求两个操作数的行数完全匹配,而result.row(rowIndex)是单行数组,和4行的expectedResult维度不兼容,导致编译失败。

简洁实现方案

方案1:利用广播+逐行比较

通过广播将单行结果扩展为和预期数组行数一致的矩阵,再逐行做近似比较,最后用any()判断是否存在匹配:

const float TOLERANCE = 1e-6f; // 根据你的需求调整容差

for (int rowIdx = 0; rowIdx < 4; ++rowIdx) {
    // 将当前结果行复制4行,和expectedResult逐行对比
    auto diff = expectedResult.rowwise() - result.row(rowIdx).replicate(4, 1);
    // 每行两个元素的绝对值都小于等于容差时,该行匹配
    auto rowMatches = diff.abs().rowwise().maxCoeff() <= TOLERANCE;
    // 只要有任意一行匹配就通过
    EXPECT_TRUE(rowMatches.any());
}

方案2:生成匹配矩阵(可选,支持重复匹配校验)

如果需要确保结果的每一行都唯一匹配预期的某一行(避免结果出现重复行但预期没有的假阳性),可以生成一个匹配矩阵,再验证是否存在合法排列:

const float TOLERANCE = 1e-6f;

// 生成4x4的布尔矩阵,matches[i][j]表示expectedResult第i行是否匹配result第j行
Eigen::Array<bool, 4, 4> matches = (expectedResult.replicate(1,4) - result.replicate(4,1)).abs() <= TOLERANCE;
matches = matches.rowwise().all(); // 该行两个元素都满足容差才算匹配

// 验证result的每一行都能找到匹配的预期行
EXPECT_TRUE(matches.colwise().any().all());

// 可选:验证匹配关系是一个排列(每行每列仅一个匹配),避免重复匹配
Eigen::PermutationMatrix<4,4> perm;
EXPECT_TRUE(matches.transpose().fullPivLu().isInvertible() && perm.linearize(matches.transpose()));

内容的提问来源于stack exchange,提问作者Emil Lundh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 22:46:34