【问题标题】:sum up vectors in a matrix, element by element in c++将矩阵中的向量相加,在 C++ 中逐个元素地求和
【发布时间】:2021-10-06 13:37:12
【问题描述】:

C++ 中是否有一种简单的方法可以逐个元素地总结构成矩阵元素的向量?我的意思是,如果我有矩阵 M[3][4],我想要带有这些组件的 sum[3] 向量:

sum[0]=M[0][0]+M[1][0]+M[2][0]
sum[1]=M[0][1]+M[1][1]+M[2][1]
sum[2]=M[0][2]+M[1][2]+M[2][2]

我发现两个向量存在this method,我想将它扩展到许多向量,特别是构成矩阵std::vector<vector<type> > Mstd::vector<type>rows,不知道先验M的维度。

【问题讨论】:

  • 您确定要sum[0] 包含第一个而不是第一个的总和吗?
  • 完全确定。如果我的矩阵是 M{ {1,2,3},{4,5,6}} 我希望 sum 为 sum={5,7,9}。
  • 我明白了。我想我会先转置矩阵,然后对行进行计算。

标签: c++ algorithm matrix sum components


【解决方案1】:

C++ 中是否有一种简单的方法可以逐个元素地总结构成矩阵元素的向量?我的意思是,如果我有矩阵 M[3][4],我想要 sum[3] 向量与这个组件:

sum[0]=M[0][0]+M[1][0]+M[2][0]
sum[1]=M[0][1]+M[1][1]+M[2][1]
sum[2]=M[0][2]+M[1][2]+M[2][2]

很遗憾,C++标准库中没有简单的方法可以添加 容器的元素列。

std::accumulate(),但很自然,它会将行元素加在一起,而不是列元素,但我们可以通过遍历矩阵内的每个列索引并加起来来解决这个问题元素一一:

#include <iostream>
#include <numeric>
#include <cstddef>
#include <vector>

// The below function assumes that all columns of your matrix have the same length
template <typename T>
std::vector<T> m_col_add(std::vector<std::vector<T>> const& mat) {
    std::vector<T> res;
    const auto column_size = mat[0].size();
    for (size_t x = 0; x < column_size; ++x)
        res.push_back(std::accumulate(mat.begin(), mat.end(), T{}, [x](T const& a, std::vector<T> const& row) {
            return a + row[x];
        }));
    return res;
}

int main() {
    std::vector<std::vector<int>> mat {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    };
    auto res = m_col_add(mat);
    for (auto const& elem : res)
        std::cout << elem << " ";
}

输出

15 18 21 24 

或者,如果您在编译时已经知道行和列的大小,并且使用的是 C++17 或更高版本,则可以使用fold expressionsstd::index_sequence&lt;&gt; 相加通过编译时扩展使元素更快:

#include <iostream>
#include <utility>
#include <cstddef>
#include <array>

template <size_t Column, typename T, size_t Rows, size_t Columns, size_t ...Sizes>
T m_col_add_impl2(std::index_sequence<Sizes...>, std::array<std::array<T, Columns>, Rows> const& mat) {
    return (mat[Sizes][Column] + ...);
}

template <typename T, size_t Rows, size_t Columns, size_t ...Sizes>
std::array<T, Columns> m_col_add_impl1(std::index_sequence<Sizes...>, std::array<std::array<T, Columns>, Rows> const& mat) {
    std::array<T, Columns> sum;
    ((sum[Sizes] = m_col_add_impl2<Sizes>(std::make_index_sequence<Rows>(), mat)), ...);
    return sum;
}

template <typename T, size_t Rows, size_t Columns>
std::array<T, Columns> m_col_add(std::array<std::array<T, Columns>, Rows> const& mat) {
    return m_col_add_impl1(std::make_index_sequence<Columns>(), mat);
}

int main() {
    std::array mat {
        std::array {1, 2, 3, 4},
        std::array {5, 6, 7, 8},
        std::array {9, 10, 11, 12}
    };
    auto res = m_col_add(mat);
    for (auto const& elem : res)
    std::cout << elem << " ";
}

输出

15 18 21 24 

【讨论】:

    【解决方案2】:

    您可以为向量定义operator+=,它允许您定义一个通用的Sum 函数,该函数接收范围的开始和结束运算符以求和,该函数适用于具有与+= 运算符一起使用的任何值类型的迭代器,例如提供+= 运算符的原始类型或(可能是嵌套的)类型向量:

    template<typename T>
    std::vector<T>& operator+=(std::vector<T>& lhs, std::vector<T> const& rhs)
    {
        if (lhs.empty())
        {
            lhs = rhs; // first summand; 0 + x = x 
        }
        else
        {    
            for (size_t i = 0; i < lhs.size(); ++i)
            {
                lhs[i] += rhs.at(i); // component-wise add
            }
        }
        return lhs;
    }
    
    // sum up elements in a given range
    template<typename IteratorType>
    typename std::iterator_traits<IteratorType>::value_type Sum(IteratorType summandBegin, IteratorType summandEnd)
    {
        typename std::iterator_traits<IteratorType>::value_type sum {}; // 0 or object created with default constructor depending on the type
        while (summandBegin != summandEnd)
        {
            sum += *summandBegin;
            ++summandBegin;
        }
        return sum;
    }
    
    // sums the first count elements of a vector
    template<typename T>
    T PartialSum(std::vector<T> const& vec, size_t count)
    {
        assert(vec.size() >= count);
        return Sum(vec.begin(), vec.begin() + count);
    }
    
    // logic for displaying
    template<typename T>
    std::ostream& operator<<(std::ostream& s, std::vector<T> const& vec)
    {
        s << '{';
        for (auto& val : vec)
        {
            s << val << ", ";
        }
        s << '}';
        return s;
    }
    
    int main(int argc, char *argv[]) {
        std::vector<std::vector<std::vector<int>>> matrix { {{1, 2},{ 3, 4},{ 5, 6}},{{7, 8},{ 9, 10},{11, 12}},{{13, 14},{ 15, 16},{ 17, 18}}};
    
        auto partialSum = PartialSum(matrix, 2);
    
        std::cout << matrix << '\n' << partialSum << '\n';
    
        std::cout << "\nSomething extra:\n";
        std::vector<std::vector<std::string>> m2 = {{"Hell" , "Wo"} , {"o ", "rld!"}, {"foo", "bar"}};
        auto message = PartialSum(m2, 2);
        for (auto& msg : message)
        {
            std::cout << msg;
        }
        std::cout << '\n';
    
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-15
      • 2013-05-04
      • 1970-01-01
      • 1970-01-01
      • 2021-01-20
      • 1970-01-01
      相关资源
      最近更新 更多