如何为满足一定条件的矩阵元素赋值



我需要从矩阵A创建新矩阵。除主对角线上的元素外,新矩阵中的所有元素都需要是矩阵A中的元素。主对角线上的奇数元素需要除以2,主对角线上偶数元素需要乘以3。

julia> A=rand(1:10 ,3,3)
3×3 Array{Int64,2}:
5  3  1
5  2  6
10  1  7

我决定从两个矩阵中创建新的矩阵。首先,我决定保留矩阵A中的所有元素,除了主对角线上的元素,在主对角线上有零的矩阵B中:

julia> B=A .* .~ I(3)
3×3 Array{Int64,2}:
0  3  1
5  0  6
10  1  0

然后我想创建矩阵C,它的主对角线与A相同,所有其他元素都是零:

julia> C=A .* one(A)
3×3 Array{Int64,2}:
5  0  0
0  2  0
0  0  7

最后,我的目标是对矩阵C进行所有更改,然后创建最终的矩阵作为

D = C + B;

我在更改主对角线时遇到问题,因为我不确定如何为满足特定条件的矩阵元素赋值。例如,如何将主对角线上的偶数元素乘以3,将主对角线的奇数元素除以2?

我尝试使用replace:replace!(x->x%2!=0 ? x/2 : x, C),但它返回错误。我试着使用C[C .% 2 .!=0],然后用它做一些事情,但我做不好。

提前感谢!

一个简单的循环怎么样?

function change_diagonal!(A)
@inbounds for i = 1:size(A,1)
if iseven(A[i,i])
A[i,i] = 3*A[i,i]
else
A[i,i] = A[i,i]/2
end
end
return A
end

这样做的一个问题是,你的矩阵是Int64类型的,奇数除以2不会产生整数。但是,一般来说,如果只想对稠密矩阵的主要元素进行运算,那么简单的循环既简单又快速。需要注意的是,这会在适当的位置修改矩阵,因此在执行操作时不会有任何内存分配。如果我们将其扩展为更通用的:

function change_diagonal!(f,A)
@inbounds for i = 1:size(A,1)
A[i,i] = f(A[i,i]) 
end
return A
end

您可以传递任何函数,该函数将映射到矩阵的对角元素上。

编辑:还有其他方法,我不知道是否更快(可能不会(,但为了完整性,这里的想法是:你可以生成一个与矩阵对角线视图相对应的向量,所以当你修改这个向量时,你就修改了原始矩阵。这里有一个生成该视图的函数:

function diagonal_view(A)
return @view A[diagind(A)]
end

现在,你可以像处理一个简单的向量一样处理对角线:

A = rand(1.0:10.0,5,5)
diagA = diagonal_view(A)
diagA .= 40.0 #all elements of the diagonal of A are changed to 40.0
map!(x->2x,diagA,diagA) # another way to modify the diagonal, doubles the values

这个问题是矩阵A的类型是Int64,奇数除以2不会产生整数。如果将奇数除以2,则结果不是Int64,(7/2(=3.5。关键是将矩阵的生成改为A=rand(1.0:10.0 , 3,3),然后replace!(x->x%2!=0 ? x/2 : x, C)replace!(x->x%2==0 ? x*3 : x, C)才能完美地工作!

非常感谢@longement3000指出这一点!

最新更新