2014-11-03 4 views
5

В настоящее время я пытаюсь преобразовать код Python в C++. Одна «маленькая» проблема заключается в изменении размеров матрицы. Можно ли изменить матрицу на C++, аналогичную функции Python reshape?Как изменить форму матрицы?

Например, в 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++. –

ответ

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

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::mat и arma::endr и т.д. Я сделал это в примере просто для ясности.

Смежные вопросы