【问题标题】:How to assign value to matrix element that satisfy a certain condition?如何为满足一定条件的矩阵元素赋值?
【发布时间】:2019-10-28 22:25:15
【问题描述】:

我需要从矩阵 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

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

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!(x->x%2!=0 ? x/2 : x, C),但它返回错误。 我尝试使用C[C .% 2 .!=0],而不是用它做点什么,但我做错了。

提前致谢!

【问题讨论】:

  • 我注意到您的配方存在问题。如果将奇数除以 2,则结果不是 Int64,(7/2) = 3.5。对吗?
  • @longemen3000 是的,你是对的。我忽略了它...你知道我该如何解决或者转换它吗?
  • 您可以将矩阵的生成从rand(1:10,3,3)更改为rand(1.0:10.0,3,3)。另一个问题是 iseven 方法不适用于浮点数,但可以用函数 my_iseven(x) = rem(x,2) == zero(x) 替换
  • @longemen3000 关键是将矩阵的生成更改为A=rand(1.0:10.0 , 3,3),然后replace!(x->x%2!=0 ? x/2 : x, C) 完美运行!非常感谢!

标签: matrix julia diagonal


【解决方案1】:

那么简单的循环呢?

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

【讨论】:

  • 非常感谢您的详细解答!我会尝试两种方式。最好的问候!
  • @VasilijeBursac 在 Julia 循环中是你的朋友。你应该习惯使用它们。它们几乎总是最快的解决方案,并且在某些/许多情况下,它们都更优雅、更易于编写和更易于阅读。 '矢量化' 实现应在易于编写时使用,而不是像您在此处遇到的矢量化代码难以编写且难以理解的情况。
  • @DNF 我肯定会习惯使用循环。两天前我开始学习 Julia,所以我还在适应它。非常感谢您的解释和建议!最好的问候!
【解决方案2】:

问题在于矩阵 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 指出这一点!

【讨论】:

    猜你喜欢
    • 2019-12-22
    • 2021-01-03
    • 1970-01-01
    • 1970-01-01
    • 2021-12-21
    • 2017-10-26
    • 2011-07-20
    • 1970-01-01
    相关资源
    最近更新 更多