【Eigen教程08】unaryExpr和NullaryExpr
原创作者:郑同学的笔记原文链接:https://zhengjunxue.blog.csdn.net/article/details/149140136。
【Eigen教程08】unaryExpr和NullaryExpr
原创作者:郑同学的笔记
原文链接:https://zhengjunxue.blog.csdn.net/article/details/149140136
一、unaryExpr(一元表达式)
-
- 作用:对矩阵/数组的每个元素应用自定义的一元函数(单输入操作)。
-
- 语法:
result = matrix.unaryExpr(const Functor& func);
- func:函数对象(如lambda、函数指针或仿函数),接受一个标量参数并返回新值。
- 立即计算:返回新对象。
- 示例:
#include <iostream>
#include <Eigen/Eigen>
using namespace Eigen;
using namespace std;
int main()
{
Eigen::MatrixXd m(2, 2);
m << 1.1, 2.2,
3.3, 4.4;
// 示例1:自定义平方函数
auto square = [](double x) { return x * x; };
Eigen::MatrixXd squared = m.unaryExpr(square);
// 示例2:带参数的缩放 (C++14)
double scale = 2.5;
auto scaler = [scale](double x) { return x * scale; };
Eigen::MatrixXd scaled = m.unaryExpr(scaler);
// 示例3:元素取整
auto rounder2 = [](double x) {
return static_cast<int>(std::round(x));
};
Eigen::MatrixXi rounded2 = m.unaryExpr(rounder2);
// 示例4:条件操作 (将负值设为0)
auto clamp = [](double x) { return x < 0 ? 0 : x; };
Eigen::MatrixXd clamped = m.unaryExpr(clamp);
return 0;
}
使用场景
元素级转换(如缩放、取整)
自定义数学运算
类型转换
-
- 关键点
函数必须为纯函数(无状态、无副作用)
支持Lambda表达式(推荐)
返回值类型自动推导
- 关键点
二、nullaryExpr(零元表达式)
Eigen::VectorXi::NullaryExpr 用于动态生成整数向量,它通过一个自定义函数或函子(functor)计算每个元素的值,无需显式循环。这种方法利用 Eigen 的表达式模板优化,可提升性能。
-
- 作用:生成新矩阵,每个元素由自定义函数动态计算(基于行列索引)。
-
- 语法:
auto mat = Eigen::MatrixXd::NullaryExpr(rows, cols, const Functor& func);
Eigen::VectorXi vec = Eigen::VectorXi::NullaryExpr(size, generator);
- func:函数对象,接受行索引 i 和列索引 j 作为参数,返回位置 (i, j) 的值。
- 惰性求值:返回表达式模板,优化计算效率。
参数说明
- rows, cols:向量的行和列
- size:向量长度(元素数量)
- generator:生成函数,接收索引i返回对应位置的值
generator
在 Eigen::VectorXi::NullaryExpr 中,生成器函数需要满足以下要求:
ReturnType generator(Eigen::Index i);
ReturnType generator(Eigen::Index i,Eigen::Index j);
输入参数:必须是 Eigen::Index 类型
返回值:必须与目标容器元素类型匹配
- 对于 VectorXi → 返回 int
- 对于 VectorXf → 返回 float
- 对于 VectorXd → 返回 double
#include <iostream>
#include <Eigen/Eigen>
using namespace Eigen;
using namespace std;
int main()
{
// 示例1:生成5x5单位矩阵
auto identity = Eigen::MatrixXd::NullaryExpr(5, 5,
[](Eigen::Index i, Eigen::Index j) { return (i == j) ? 1.0 : 0.0; });
// 示例2:创建渐变矩阵 (行索引 + 列索引)
auto gradient = Eigen::MatrixXd::NullaryExpr(3, 4,
[](Eigen::Index i, Eigen::Index j) { return i + j; });
// 示例3:极坐标转换 (r = sqrt(x^2+y^2))
const int size = 100;
auto polar = Eigen::MatrixXd::NullaryExpr(size, size,
[size](Eigen::Index i, Eigen::Index j) {
double x = j - size / 2.0;
double y = i - size / 2.0;
return std::sqrt(x * x + y * y);
});
return 0;
}
使用场景
动态生成矩阵(如坐标网格、渐变、自定义模式)
替代循环初始化
-
- 关键点
生成器函数签名:T f(Eigen::Index row, Eigen::Index col)
- 关键点
支持按需计算
二、 基础示例:
1、生成平方序列 [0, 1, 4, 9, 16]
#include <Eigen/Dense>
#include <iostream>
int main() {
int size = 5;
// 使用 lambda 定义生成器 (计算 i²)
Eigen::VectorXi vec = Eigen::VectorXi::NullaryExpr(size,
[](Eigen::Index i) { return i * i; }
);
std::cout << vec.transpose() << std::endl;
// 输出: 0 1 4 9 16
return 0;
}
2、完整修正示例:生成随机数
#include <Eigen/Dense>
#include <iostream>
#include <random>
int main() {
const int size = 5;
// 1. 创建随机数生成器(返回 int)
std::random_device rd;
std::mt19937 rng(rd());
std::uniform_int_distribution<int> dist(0, 99);
// 2. 使用 NullaryExpr(生成器返回类型 int 匹配 VectorXi)
Eigen::VectorXi rand_vec = Eigen::VectorXi::NullaryExpr(size,
[&](Eigen::Index i) -> int { // 显式声明返回类型
return dist(rng);
}
);
// 3. 验证类型匹配
static_assert(
std::is_same_v<
decltype(rand_vec)::Scalar, // VectorXi 的元素类型
int // 生成器返回类型
>,
"类型不匹配!"
);
std::cout << "随机向量: " << rand_vec.transpose() << std::endl;
return 0;
}
三、关键区别
| 特性 | unaryExpr | nullaryExpr |
|---|---|---|
| 输入来源 | 已有矩阵的元素 | 无输入(通过索引生成值) |
| 参数 | 单个标量值 | 行列索引 (i, j) |
| 用途 | 元素级转换(如log, sin) | 动态生成矩阵(如单位矩阵) |
四、相关解析:
static_assert( // 编译时断言,如果条件不满足则编译失败
std::is_same_v< // 类型特性检查:判断两个类型是否完全相同
decltype(rand_vec)::Scalar, // 获取 rand_vec 的元素类型
int // 期望的类型(int)
>,
"类型不匹配!" // 如果断言失败,显示的错误信息
);
关键组件详解:
1、decltype(rand_vec)::Scalar
- decltype(rand_vec):获取变量 rand_vec 的编译时类型(Eigen::VectorXi)
- ::Scalar:Eigen 容器的内嵌类型别名,表示容器元素的类型
- 对于 Eigen::VectorXi,Scalar 就是 int
2、std::is_same_v<…>
C++17 引入的模板变量(等同于 std::is_same<…>::value)
检查两个类型是否完全相同
如果类型相同 → 值为 true
如果类型不同 → 值为 false
3、static_assert(condition, message)
编译时断言:在编译阶段检查条件
如果条件为 true → 编译继续
如果条件为 false → 编译失败,显示指定的错误信息
对比其他类型获取方式
| 方法 | 特点 | 示例 |
|---|---|---|
| decltype(expr) | 获取表达式的确切类型(包括引用和const) | decltype(x) → int |
| auto | 自动推导变量类型(会移除引用和const限定符) | auto y = x → int |
| std::is_same_v<T,U> | 编译时比较两个类型是否相同(常与 decltype 配合使用) | std::is_same_v<int, float> → false |
更多推荐


所有评论(0)