Tạo và khởi tạo ma trận và vector
Có nhiều cách để khai báo và khởi tạo ma trận và vector. Chúng có thể được chia thành nhiều loại theo mục đích sử dụng.
- Khai báo mà không chỉ định kích thước
- Khai báo với kích thước được chỉ định
- Khai báo kèm khởi tạo
- Các phương thức tạo tĩnh
- Các phương thức cấu hình và khởi tạo không tĩnh (tái cấu hình)
Cách tạo đơn giản nhất là khai báo mà không chỉ định kích thước, tức là không cấp phát bộ nhớ cho dữ liệu. Để làm điều này, chỉ cần chỉ định kiểu và tên biến:
matrix matrix_a; // ma trận kiểu double
matrix<double> matrix_a1; // ma trận kiểu double trong hàm hoặc mẫu lớp
matrix<float> matrix_a2; // ma trận kiểu float
vector vector_v; // vector kiểu double
vector<double> vector_v1; // cách khác để tạo vector kiểu double
vector<float> vector_v2; // vector kiểu float
2
3
4
5
6
Sau đó, bạn có thể thay đổi kích thước của các đối tượng đã tạo và điền chúng bằng các giá trị mong muốn. Chúng cũng có thể được sử dụng trong các phương thức tích hợp của ma trận và vector để lấy kết quả tính toán. Tất cả các phương thức này sẽ được thảo luận theo nhóm trong các phần của chương này.
Bạn có thể khai báo một ma trận hoặc vector với kích thước được chỉ định. Điều này sẽ cấp phát bộ nhớ nhưng không kèm khởi tạo. Để làm điều này, sau tên biến trong dấu ngoặc đơn, chỉ định kích thước (đối với ma trận, số đầu tiên là số hàng và số thứ hai là số cột):
matrix matrix_a(128, 128); // có thể chỉ định dưới dạng tham số
matrix<double> matrix_a1(nRows, nCols); // cả hằng số và biến
matrix<float> matrix_a2(nRows, 1); // tương tự vector cột
vector vector_v(256);
vector<double> vector_v1(nSize);
vector<float> vector_v2(nSize + 16); // biểu thức làm tham số
2
3
4
5
6
Cách thứ ba để tạo đối tượng là khai báo kèm khởi tạo. Kích thước của ma trận và vector trong trường hợp này được xác định bởi chuỗi khởi tạo được chỉ định trong dấu ngoặc nhọn:
matrix matrix_a = {{0.1, 0.2, 0.3}, {0.4, 0.5, 0.6}};
matrix<double> matrix_a1 = matrix_a; // phải là ma trận cùng kiểu
matrix<float> matrix_a2 = {{1, 2}, {3, 4}};
vector vector_v = {-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5};
vector<double> vector_v1 = {1, 5, 2.4, 3.3};
vector<float> vector_v2 = vector_v1; // phải là vector cùng kiểu
2
3
4
5
6
Ngoài ra còn có các phương thức tĩnh để tạo ma trận và vector với kích thước chỉ định và khởi tạo theo một cách nhất định (đặc biệt cho một dạng chuẩn tắc cụ thể). Tất cả đều được liệt kê dưới đây và có nguyên mẫu tương tự (vector khác ma trận chỉ ở việc không có chiều thứ hai).
static matrix<T> matrix<T>::Eye∫Tri(const ulong rows, const ulong cols, const int diagonal = 0);
static matrix<T> matrix<T>::Identity∫Ones∫Zeros(const ulong rows, const ulong cols);
static matrix<T> matrix<T>::Full(const ulong rows, const ulong cols, const double value);
Eye
tạo ma trận với các số 1 trên đường chéo được chỉ định và số 0 ở các vị trí khácTri
tạo ma trận với các số 1 trên và dưới đường chéo được chỉ định và số 0 ở các vị trí khácIdentity
tạo ma trận đơn vị với kích thước chỉ địnhOnes
tạo ma trận (hoặc vector) chứa toàn số 1Zeros
tạo ma trận (hoặc vector) chứa toàn số 0Full
tạo ma trận (hoặc vector) chứa toàn giá trị được chỉ định cho tất cả phần tử
Nếu cần, bạn có thể biến bất kỳ ma trận hiện có nào thành ma trận đơn vị, bằng cách áp dụng phương thức không tĩnh Identity
(không có tham số).
Hãy thể hiện các phương thức này trong thực tế:
matrix matrix_a = matrix::Eye(4, 5, 1);
matrix<double> matrix_a1 = matrix::Full(3, 4, M_PI);
matrixf matrix_a2 = matrixf::Identity(5, 5);
matrixf<float> matrix_a3 = matrixf::Ones(5, 5);
matrix matrix_a4 = matrix::Tri(4, 5, -1);
vector vector_v = vector::Ones(256);
vectorf vector_v1 = vector<float>::Zeros(16);
vector<float> vector_v2 = vectorf::Full(128, float_value);
2
3
4
5
6
7
8
Ngoài ra, còn có các phương thức không tĩnh để khởi tạo ma trận/vector với các giá trị cho trước: Init
và Fill
.
void matrix<T>::Init(const ulong rows, const ulong cols, func_reference rule = NULL, ...)
void matrix<T>::Fill(const T value)
Một lợi thế quan trọng của phương thức Init
(cũng có trong các hàm tạo) là khả năng chỉ định trong tham số một hàm khởi tạo để điền các phần tử của ma trận/vector theo một quy luật nhất định (xem ví dụ dưới đây).
Tham chiếu đến hàm như vậy có thể được truyền sau kích thước bằng cách chỉ định định danh của nó mà không có dấu ngoặc kép trong tham số rules
(đây không phải là con trỏ theo nghĩa của typedef (*pointer)(...) và cũng không phải chuỗi chứa tên).
Hàm khởi tạo phải có tham chiếu đến đối tượng được điền làm tham số đầu tiên và cũng có thể có các tham số bổ sung: trong trường hợp này, các giá trị cho chúng được truyền vào Init
hoặc hàm tạo sau tham chiếu hàm. Nếu liên kết rule
không được chỉ định, nó sẽ chỉ tạo một ma trận với kích thước được chỉ định.
Phương thức Init
cũng cho phép thay đổi cấu hình ma trận.
Hãy xem tất cả những gì đã nêu trên bằng các ví dụ nhỏ.
matrix m(2, 2);
m.Fill(10);
Print("matrix m \n", m);
/*
matrix m
[[10,10]
[10,10]]
*/
m.Init(4, 6);
Print("matrix m \n", m);
/*
matrix m
[[10,10,10,10,0.0078125,32.00000762939453]
[0,0,0,0,0,0]
[0,0,0,0,0,0]
[0,0,0,0,0,0]]
*/
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Ở đây phương thức Init
được sử dụng để thay đổi kích thước của một ma trận đã khởi tạo, dẫn đến các phần tử mới được điền bằng các giá trị ngẫu nhiên.
Hàm sau đây điền ma trận với các số tăng theo cấp số nhân:
template<typename T>
void MatrixSetValues(matrix<T> &m, const T initial = 1)
{
T value = initial;
for(ulong r = 0; r < m.Rows(); r++)
{
for(ulong c = 0; c < m.Cols(); c++)
{
m[r][c] = value;
value *= 2;
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
Sau đó, nó có thể được sử dụng để tạo một ma trận.
void OnStart()
{
matrix M(3, 6, MatrixSetValues);
Print("M = \n", M);
}
2
3
4
5
Kết quả thực thi là:
M =
[[1,2,4,8,16,32]
[64,128,256,512,1024,2048]
[4096,8192,16384,32768,65536,131072]]
2
3
4
Trong trường hợp này, các giá trị cho tham số của hàm khởi tạo không được chỉ định sau định danh của nó trong lời gọi hàm tạo, do đó giá trị mặc định (1) được sử dụng. Nhưng chúng ta có thể, ví dụ, truyền giá trị bắt đầu là -1 cho cùng MatrixSetValues
, điều này sẽ điền ma trận với một hàng số âm.
matrix M(3, 6, MatrixSetValues, -1);