2014-11-03 105 views
5

我目前正试图将一些Python代码转换为C++。一个“小”问题是改变矩阵的尺寸。是否有可能使用类似于Python reshape函数的C++重塑矩阵?如何重塑矩阵?

例如,在Python中,我可以使用numpy轻松创建一个数组,并轻松重构尺寸。

a = np.array([[1,2,3],[4,5,6]]) 
>>> a.reshape(3,2) 
array([[1, 2], 
     [3, 4], 
     [5, 6]]) 

我怎么能在C++中做到这一点?也许这是一个简单的问题,但我完全无法做到这一点。我已经在OpenCV库中看到了这个,Mathere然而,它被证明是非常难以与MinGW正常工作,更不用说单一功能的一个非常大的补充。如果这可以通过“基本”功能来实现,那将是理想的。

+0

这实际上是一个非常棘手的问题。在NumPy中很容易,因为NumPy数组实际上会跟踪它们的步幅和形状; [这篇文章](http://arxiv.org/pdf/1102.1523)描述了这个结构,甚至可以为C++程序提供灵感。 – 2014-11-03 19:16:16

回答

4

至于存储器被连续地(例如,纯C阵列)铺设,可以重新解释具有不同指数式中:

int array[2][3] = { { 1, 2, 3 }, 
         { 4, 5, 6 } 
        }; 

// Reinterpret the array with different indices 
int(*array_pointer)[3][2] = reinterpret_cast<int(*)[3][2]>(array); 

for (int x = 0; x < 3; ++x) { 
    for (int y = 0; y < 2; ++y) 
     std::cout << (*array_pointer)[x][y] << " "; 
    std::cout << std::endl; 
} 
// Output: 
// 1 2 
// 3 4 
// 5 6 

Example

上面仅仅是示出了示例问题真的归结为如何在您的矩​​阵类中布置内存。

如果您的班级在内部使用线性索引std::vector<int>,只需重新解释这些索引以适应您的访问模式就足够了。

+1

这正是我所期待的。谢谢! – cdeterman 2014-11-03 17:59:19

0

这取决于您使用的矩阵类。如果你写你 自己:常见的有两种实现方法:一种 std::vector<double>,与指数计算找到平 指数和std::vector<std::vector<double>>,一类 不变,所有的外部矢量的成员必须有 的相同的尺寸。如果你使用第一个,重塑很容易,只要总尺寸不变(很难想象它会是什么意思)。如果您使用第二个,则重塑 可能需要构建具有新形状的副本。

0

在C++中没有标准的矩阵库,所以当涉及到矩阵时你自己。存储矩阵数据的一种方式是以一个简单的数组。访问单独的行和列时,您必须执行自己的行和列算术。在你的情况下,重塑然后通过交换行和列的大小来免费。

如果您想要矩阵库,请尝试:GLM

3

下面是使用一个例子boost::ublas

#include <iostream> 
#include <boost/numeric/ublas/matrix.hpp> 

//... 

using namespace boost::numeric::ublas; 

matrix<double> a(2, 3); 
a(0, 0) = 1; 
a(0, 1) = 2; 
a(0, 2) = 3; 
a(1, 0) = 4; 
a(1, 1) = 5; 
a(1, 2) = 6; 
matrix<double> r(3, 2, a.data()); 

for (int i = 0;i < 3;++i) 
{ 
    for (int j = 0;j < 2;++j) 
    std::cout << r(i, j) << ", "; 
    std::cout << std::endl; 
} 

1,2

3,4

5,6

1

一个非常轻巧,轻松使用的C++线性代数库是Armadillo,它提供reshape功能。

#include <armadillo> 
using namespace arma; 
int main() 
{ 
    // C++11 
    // mat a = { { 1, 2, 3 }, 
    // { 4, 5, 6 } }; 

    // C++98 
    mat a; 
    a << 1 << 2 << 3 << endr 
     << 2 << 4 << 6 << endr; 

    a.reshape(3, 2); 
    a.print(); 

    return 0; 
} 

注:我建议不要做using namespace arma;,而是做arma::matarma::endr,等我做到了在例子只是为了清楚起见。