如何用std::transform实现二维矩阵乘法?求技术建议与参考资料
用std::transform实现二维矩阵乘法的方案
当然可以用std::transform实现二维矩阵乘法,但得先理清它的适用逻辑——transform本质是做元素级的映射转换,而矩阵乘法不是简单的元素对元素相乘(那是哈达玛积),而是需要行与列的点积运算,所以得搭配std::inner_product这类算法来完成,不能直接把矩阵的迭代器塞进去就完事。
核心思路
矩阵乘法的规则是:若矩阵A是m×n,矩阵B是n×p,结果矩阵C是m×p,其中C[i][j]等于A的第i行与B的第j列的点积。我们可以通过两层std::transform来实现:
- 外层
transform遍历A的每一行,对应生成结果矩阵C的每一行; - 内层
transform遍历B的每一列,计算A当前行与该列的点积,填充C当前行的每个元素; - 点积的计算直接用
std::inner_product,它正好是为两个序列的点积运算设计的。
完整代码示例
这里针对你提到的vector<vector<T>>*指针形式做了适配:
#include <vector> #include <algorithm> #include <numeric> #include <stdexcept> template<typename T> std::vector<std::vector<T>> matrixMultiply(const std::vector<std::vector<T>>* matA, const std::vector<std::vector<T>>* matB) { // 先做合法性校验:指针非空、矩阵非空、行列数匹配 if (!matA || !matB || matA->empty() || matB->empty() || matA->at(0).size() != matB->size()) { throw std::invalid_argument("Matrix dimensions are invalid for multiplication"); } const auto& A = *matA; const auto& B = *matB; const size_t rowsA = A.size(); const size_t colsA = A[0].size(); const size_t colsB = B[0].size(); // 提前初始化结果矩阵的结构 std::vector<std::vector<T>> result(rowsA, std::vector<T>(colsB)); // 外层transform:遍历A的每一行,生成result的对应行 std::transform(A.begin(), A.end(), result.begin(), [&](const std::vector<T>& rowA) { std::vector<T> currentRow(colsB); // 内层transform:遍历B的每一列索引,计算点积填充currentRow std::transform(std::begin(B[0]), std::end(B[0]), currentRow.begin(), [&](size_t colIdx) { // inner_product计算rowA与B的第colIdx列的点积 return std::inner_product( rowA.begin(), rowA.end(), B.begin(), T{}, // 初始值 std::plus<T>(), // 累加器 [colIdx](const T& a_val, const std::vector<T>& b_row) { return a_val * b_row[colIdx]; // 对应元素相乘 } ); }); return currentRow; }); return result; }
为什么你之前的尝试失败?
你直接传入data.begin()到transform中,相当于让transform对矩阵的每一行(vector<T>类型)做转换,但没有指定正确的转换逻辑——transform不知道你需要做行与列的点积,它只会按你提供的仿函数去处理单个元素。如果没有配套的点积逻辑,自然无法得到正确的矩阵乘法结果。
注意事项
- 上面的实现中,访问B的列元素是按列索引取每一行的对应位置,而
vector是行优先存储的,所以当矩阵很大时,会有缓存命中率的问题,性能可能不如先转置B再做行×行的点积。如果追求性能,可以先对B做转置优化; - 模板支持任意数值类型(int、float、double等),只要该类型支持
+和*运算即可; - 一定要做合法性校验,避免空指针、空矩阵或行列数不匹配的情况。
内容的提问来源于stack exchange,提问作者Rocking chief
相关产品推荐
相关产品推荐

