如何为满足特定条件的矩阵元素分配值?

时间:2019-10-28 22:25:15

标签: matrix julia diagonal

我需要从矩阵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中,该矩阵B在主对角线上为零:

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

然后我要创建矩阵C,该矩阵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]而不是使用它,但是我做对了。

谢谢!

2 个答案:

答案 0 :(得分:2)

一个简单的循环是什么?

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

答案 1 :(得分:1)

问题在于矩阵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)完美地工作!

非常感谢@ longemen3000指出了这一点!

相关问题