2010-10-18 39 views
40

Giả sử tôi có một NxN ma trận A, một V vector chỉ số bao gồm một tập hợp con của các con số 1: N, và một giá trị K, và tôi muốn làm điều này:Làm cách nào để gán giá trị trên đường chéo?

for i = V 
    A(i,i) = K 
end 

Có cách nào để làm điều này trong một tuyên bố w/vectorization?

ví dụ: A (một cái gì đó) = K

Tuyên bố A(V,V) = K sẽ không hoạt động, nó gán các phần tử đường chéo, và đây không phải là những gì tôi muốn. ví dụ:

>> A = zeros(5); 
>> V = [1 3 4]; 
>> A(V,V) = 1 

A = 

1  0  1  1  0 
0  0  0  0  0 
1  0  1  1  0 
1  0  1  1  0 
0  0  0  0  0 

Trả lời

60

Tôi thường sử dụng EYE cho rằng:

A = magic(4) 
A(logical(eye(size(A)))) = 99 

A = 
    99  2  3 13 
    5 99 10  8 
    9  7 99 12 
    4 14 15 99 

Ngoài ra, bạn chỉ có thể tạo danh sách các chỉ số tuyến tính, vì từ một yếu tố đường chéo để tiếp theo, phải mất nRows+1 bước sau:

[nRows,nCols] = size(A); 
A(1:(nRows+1):nRows*nCols) = 101 
A = 
    101  2  3 13 
    5 101 10  8 
    9  7 101 12 
    4 14 15 101 

Nếu bạn chỉ muốn truy cập một tập hợp con của các yếu tố đường chéo, bạn cần phải tạo ra một danh sách các chỉ số đường chéo:

subsetIdx = [1 3]; 
diagonalIdx = (subsetIdx-1) * (nRows + 1) + 1; 
A(diagonalIdx) = 203 
A = 
    203  2  3 13 
    5 101 10  8 
    9  7 203 12 
    4 14 15 101 

Ngoài ra, bạn có thể tạo một mảng chỉ số logic sử dụng diag (chỉ hoạt động cho mảng vuông)

diagonalIdx = false(nRows,1); 
diagonalIdx(subsetIdx) = true; 
A(diag(diagonalIdx)) = -1 
A = 
    -1  2  3 13 
    5 101 10  8 
    9  7 -1 12 
    4 14 15 101 
+0

mát mẻ, nó hoạt động! sẽ chấp nhận khi bộ đếm thời gian ngu ngốc chạy hết –

+0

@ Jason S: Cảm ơn! Tôi thực sự thấy đây là một vấn đề khó chịu; Tôi thường cố gắng sử dụng 'diag' trước, trước khi tôi nhớ sử dụng 'eye' – Jonas

+0

cho ví dụ cuối cùng thứ hai, tôi đề nghị sử dụng hàm sub2ind của MATLAB để tìm các chỉ số tuyệt đối. Theo tôi, đây là cách tiếp cận thẳng thắn nhất (và dễ đọc nhất) và có thể thay thế hai đề xuất cuối cùng của bạn. – tc88

21
>> tt = zeros(5,5) 
tt = 
    0  0  0  0  0 
    0  0  0  0  0 
    0  0  0  0  0 
    0  0  0  0  0 
    0  0  0  0  0 
>> tt(1:6:end) = 3 
tt = 
    3  0  0  0  0 
    0  3  0  0  0 
    0  0  3  0  0 
    0  0  0  3  0 
    0  0  0  0  3 

và tổng quát hơn:

>> V=[1 2 5]; N=5; 
>> tt = zeros(N,N); 
>> tt((N+1)*(V-1)+1) = 3 
tt = 
    3  0  0  0  0 
    0  3  0  0  0 
    0  0  0  0  0 
    0  0  0  0  0 
    0  0  0  0  3 

này được dựa trên thực tế là ma trận có thể được truy cập dưới dạng mảng một chiều (vectơ), trong đó 2 chỉ số (m, n) được thay thế bằng ánh xạ tuyến tính m * N + n.

+0

Tôi chỉ thấy giải pháp của bạn sau khi tôi đã gửi chỉnh sửa. 1 để được nhanh hơn, mặc dù giải pháp của tôi là tổng quát hơn một chút :) – Jonas

+1

Tôi thực sự thích phương thức tt (1: n + 1: end), thực sự sạch sẽ! – Erika

2
A = zeros(7,6); 
V = [1 3 5]; 

[n m] = size(A); 
diagIdx = 1:n+1:n*m; 
A(diagIdx(V)) = 1 

A = 
    1  0  0  0  0  0 
    0  0  0  0  0  0 
    0  0  1  0  0  0 
    0  0  0  0  0  0 
    0  0  0  0  1  0 
    0  0  0  0  0  0 
    0  0  0  0  0  0 
2

Giả sử K là giá trị. Lệnh

A=A-diag(K-diag(A)) 

có thể nhanh hơn một chút

>> A=randn(10000,10000); 

>> tic;A(logical(eye(size(A))))=12;toc 

Thời gian đã qua là 0,517575 giây.

>> tic;A=A+diag((99-diag(A)));toc 

Thời gian đã trôi qua là 0,353408 giây.

Nhưng nó tiêu thụ nhiều bộ nhớ hơn.

+0

Tôi đã sử dụng 'A (lôgic (mắt (kích thước (A))) = K' linh hoạt nhanh và đáng tin cậy – Vass

1

Tôi muốn sử dụng sub2ind và vượt qua các chỉ số đường chéo như cả hai tham số x và y:

A = zeros(4) 
V=[2 4] 

idx = sub2ind(size(A), V,V) 
% idx = [6, 16] 

A(idx) = 1 

% A = 
% 0  0  0  0 
% 0  1  0  0 
% 0  0  0  0 
% 0  0  0  1 
Các vấn đề liên quan