2014-11-03 26 views
5

Tôi hiện đang cố gắng chuyển đổi một số mã Python thành C++. Một vấn đề 'nhỏ' đang thay đổi kích thước của một ma trận. Có thể định hình lại ma trận trong C++ tương tự như hàm Python reshape không?Cách định hình lại ma trận?

Ví dụ, trong Python tôi có thể dễ dàng tạo một mảng với numpy và dễ dàng định hình lại kích thước.

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

Tôi có thể làm điều này bằng C++ như thế nào? Có lẽ đây là một câu hỏi đơn giản nhưng tôi hoàn toàn không thể làm được điều này. Tôi đã thấy điều này trong thư viện OpenCV với các lớp Mathere tuy nhiên nó được chứng minh là cực kỳ khó khăn để làm việc đúng với MinGW, chưa kể đến một bổ sung rất lớn cho một chức năng duy nhất. Nó sẽ là lý tưởng nếu điều này là có thể với chức năng 'cơ sở'.

+0

Đây thực sự là một câu hỏi rất phức tạp. Trong NumPy nó dễ dàng bởi vì mảng NumPy thực sự theo dõi các bước tiến và hình dạng của chúng; [bài viết này] (http://arxiv.org/pdf/1102.1523) mô tả cấu trúc và có thể cung cấp nguồn cảm hứng ngay cả đối với các chương trình C++. –

Trả lời

4

Theo như bộ nhớ được trình bày liên tục kế nhau (ví dụ như đồng bằng C mảng), bạn có thể diễn giải lại các loại với chỉ số khác nhau:

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

Trên đây chỉ là một ví dụ để hiển thị rằng vấn đề thực sự tóm tắt cách bộ nhớ được đặt ra trong lớp ma trận của bạn.

Trong trường hợp lớp học của bạn sử dụng std::vector<int> nội bộ với chỉ mục tuyến tính, đủ để diễn giải lại các chỉ mục này cho phù hợp với mẫu truy cập của bạn.

+1

Đây chính xác là những gì tôi đang tìm kiếm. Cảm ơn bạn! – cdeterman

0

Tùy thuộc vào lớp ma trận bạn đang sử dụng. Nếu bạn viết của bạn riêng: có hai kỹ thuật phổ biến thực hiện: một std::vector<double>, với các tính toán chỉ số để tìm ra index bằng phẳng, và một std::vector<std::vector<double>>, với một lớp bất biến mà tất cả các thành viên của vector ngoài phải có sự cùng cỡ. Nếu bạn sử dụng lần đầu tiên, định hình lại dễ dàng, miễn là vì tổng kích thước không thay đổi (và thật khó để tưởng tượng những gì điều đó có nghĩa là nếu không). Nếu bạn sử dụng thứ hai, định hình lại có thể sẽ yêu cầu tạo bản sao có hình dạng mới.

0

Không có thư viện ma trận chuẩn nào trong C++, do đó bạn là của riêng bạn khi nói đến Ma trận. Một cách để lưu trữ dữ liệu ma trận nằm trong một mảng đơn giản. Sau đó, bạn phải thực hiện phép tính hàng và cột của riêng mình khi truy cập các hàng và cột riêng lẻ. Trong trường hợp của bạn, việc định hình lại sẽ miễn phí bằng cách hoán đổi kích thước hàng và cột.

Nếu bạn muốn có thư viện ma trận, hãy thử: GLM.

3

Dưới đây là một ví dụ sử dụng 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

Một rất nhẹ, dễ dàng thư viện đại số tuyến tính C++ sử dụng là Armadillo và nó cung cấp chức năng 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; 
} 

Lưu ý: Tôi muốn đề nghị không nên làm using namespace arma; và thay vào đó làm arma::matarma::endr, vv Tôi đã làm điều đó trong ví dụ này chỉ cho rõ ràng.

Các vấn đề liên quan