Matrix 如何给满足一定条件的矩阵元素赋值?

Matrix 如何给满足一定条件的矩阵元素赋值?,matrix,julia,diagonal,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中的主对角线上有零: julia> B=A .* .~ I(3) 3×3 Array

我需要从矩阵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进行所有更改,然后创建最终矩阵A

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

一个简单的循环怎么样

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=rand1.0:10.0,3,3,然后替换!x->x%2=0 ? x/2:x,C并更换!x->x%2==0?x*3:x,C工作得很好


非常感谢@longemen3000指出这一点

问题是矩阵A的类型是Int64,奇数除以2不会产生整数。如果将奇数除以2,则结果不是Int64,7/2=3.5。 关键是将矩阵的生成更改为A=rand1.0:10.0,3,3,然后替换!x->x%2=0 ? x/2:x,C并更换!x->x%2==0?x*3:x,C工作得很好


非常感谢@longemen3000指出这一点

我注意到你的表述中有一个问题。如果将奇数除以2,则结果不是Int64,7/2=3.5。是吗?@longemen3000是的,你是对的。我忽略了它。。。你知道我如何解决这个问题或者转换它吗?你可以改变矩阵的生成,从rand1:10,3,3到rand1.0:10.0,3,3。另一个问题是iseven方法不能处理浮点数,但可以用函数my_isevenx=remx,2=zerox@longemen3000关键是将矩阵的生成更改为A=rand1.0:10.0,3,3,然后替换!x->x%2=0 ? x/2:x,C工作得很好!非常感谢你!我注意到你的表述中有一个问题。如果将奇数除以2,则结果不是Int64,7/2=3.5。是吗?@longemen3000是的,你是对的。我忽略了它。。。你知道我如何解决这个问题或者转换它吗?你可以改变矩阵的生成,从rand1:10,3,3到rand1.0:10.0,3,3。另一个问题是iseven方法不适用于浮点num
但是可以用函数my_isevenx=remx,2=zerox@longemen3000关键是将矩阵的生成更改为A=rand1.0:10.0,3,3,然后替换!x->x%2=0 ? x/2:x,C工作得很好!非常感谢你!非常感谢您的详细回答!我会尝试两种方法。致以最良好的祝愿@朱莉娅·洛普斯的瓦西里耶布尔萨克是你的朋友。你应该习惯使用它们。它们几乎总是最快的解决方案,在某些/许多情况下,它们都更优雅、更易于编写,也更易于阅读。”“矢量化”实现应该在易于编写的情况下使用,而不是像您这里这样的情况,矢量化代码难以编写且难以理解。@DNF我肯定会习惯使用循环。我两天前就开始学习朱莉娅了,所以我还是习惯了。非常感谢您的解释和建议!顺致敬意,非常感谢您的详细回答!我会尝试两种方法。致以最良好的祝愿@朱莉娅·洛普斯的瓦西里耶布尔萨克是你的朋友。你应该习惯使用它们。它们几乎总是最快的解决方案,在某些/许多情况下,它们都更优雅、更易于编写,也更易于阅读。”“矢量化”实现应该在易于编写的情况下使用,而不是像您这里这样的情况,矢量化代码难以编写且难以理解。@DNF我肯定会习惯使用循环。我两天前就开始学习朱莉娅了,所以我还是习惯了。非常感谢您的解释和建议!顺致敬意,