Eigen 在不丢失 NaN 值的情况下将向量与某些 NaN 值进行比较
Eigen compare vectors with some NaN values WITHOUT losing the NaN values
查看下面的代码:
Eigen::VectorXf vec1(3);
vec1(0) = 231;
vec1(1) = 512;
vec1(2) = 213;
Eigen::VectorXf vec2(3);
vec2(0) = 10;
vec2(1) = std::numeric_limits<double>::quiet_NaN();
vec2(2) = 2213;
std::cout << (vec1.array() < vec2.array()) << std::endl;
输出:
0,
0,
1
但是我不想丢失 NaN 值,所以我想要的输出如下:
0,
南,
1
我知道我可以通过遍历初始向量,记录任何 NaN 值的位置,然后用这些位置更新输出来实现这一点。
但是这有点混乱,我希望代码尽可能高效(即避免任何不必要的 for 循环)。
所以我的问题是,有没有一种简单的方法可以在不丢失 NaN 值的情况下实现这种比较?
这是可能的,但有几点需要注意。
首先是比较结果的类型不会相同。 Eigen 中按分量比较的结果将是一个整数数组(0 或 1)。如果您想要可以是 0、1 或 NaN
的值,则必须将其转换为 float
。在 Eigen 中,您必须使用显式转换操作。
请注意,正如评论所指出的,结果不会告诉您不等式的哪一侧首先有 NaN
s。
现在,您可以算术计算了。如果我们将所有内容都转换为 float
的向量,我们可以依靠 NaN
的算术属性来传播它们:
VectorXf compare_with_nans(const VectorXf& vec1, const VectorXf& vec2) {
const VectorXf zero_or_nan_1 = vec1 - vec1;
const VectorXf zero_or_nan_2 = vec2 - vec2;
const VectorXf compare = (vec1.array() < vec2.array()).matrix().cast<float>();
return compare + zero_or_nan_1 + zero_or_nan2;
}
这取决于以下事实:如果 x
是常规值,x-x
将产生 0
,如果 x
是 [=11=,则 NaN
],因此 vec1-vec1
将在其组件值为常规数字的位置为 0,在其他任何地方为 NaN
。
最后添加 zero_or_nan
向量上的 NaN
将污染原始向量中包含 NaN
的行上的常规值。
查看下面的代码:
Eigen::VectorXf vec1(3);
vec1(0) = 231;
vec1(1) = 512;
vec1(2) = 213;
Eigen::VectorXf vec2(3);
vec2(0) = 10;
vec2(1) = std::numeric_limits<double>::quiet_NaN();
vec2(2) = 2213;
std::cout << (vec1.array() < vec2.array()) << std::endl;
输出:
0, 0, 1
但是我不想丢失 NaN 值,所以我想要的输出如下:
0, 南, 1
我知道我可以通过遍历初始向量,记录任何 NaN 值的位置,然后用这些位置更新输出来实现这一点。
但是这有点混乱,我希望代码尽可能高效(即避免任何不必要的 for 循环)。
所以我的问题是,有没有一种简单的方法可以在不丢失 NaN 值的情况下实现这种比较?
这是可能的,但有几点需要注意。
首先是比较结果的类型不会相同。 Eigen 中按分量比较的结果将是一个整数数组(0 或 1)。如果您想要可以是 0、1 或 NaN
的值,则必须将其转换为 float
。在 Eigen 中,您必须使用显式转换操作。
请注意,正如评论所指出的,结果不会告诉您不等式的哪一侧首先有 NaN
s。
现在,您可以算术计算了。如果我们将所有内容都转换为 float
的向量,我们可以依靠 NaN
的算术属性来传播它们:
VectorXf compare_with_nans(const VectorXf& vec1, const VectorXf& vec2) {
const VectorXf zero_or_nan_1 = vec1 - vec1;
const VectorXf zero_or_nan_2 = vec2 - vec2;
const VectorXf compare = (vec1.array() < vec2.array()).matrix().cast<float>();
return compare + zero_or_nan_1 + zero_or_nan2;
}
这取决于以下事实:如果 x
是常规值,x-x
将产生 0
,如果 x
是 [=11=,则 NaN
],因此 vec1-vec1
将在其组件值为常规数字的位置为 0,在其他任何地方为 NaN
。
最后添加 zero_or_nan
向量上的 NaN
将污染原始向量中包含 NaN
的行上的常规值。