2026a

# 常用易混淆函数


# min 与 minimum 区别

  • min的函数声明:

    min(x, y, ...)
    

    例如:

    min(2, 5, 1) # 返回 1
    
  • minimum的函数声明:

    # 返回集合中最小元素
    minimum(itr; [init])
    
    # 对集合元素调用函数 f,并返回最小结果
    minimum(f, itr; [init])
    
    minimum(A::AbstractArray; dims)
    minimum(f, A::AbstractArray; dims)
    

    例如:

    x = [1 3 5; 2 -4 6]
    #=
    2×3 Matrix{Int64}:
    1   3  5
    2  -4  6
    =#
    
    minimum(x) # 返回 -4,等价于 min(x...)
    
    minimum(x, dims=1) # 维度 1 上的最小值
    #=
    1×3 Matrix{Int64}:
    1  -4  5
    =#
    
    minimum(x, dims=2) # 维度 2 上的最小值
    #=
    2×1 Matrix{Int64}:
      1
    -4
    =#
    
    minimum(abs, x, dims=2) # 维度 2 上的取绝对值最小值
    #=
    2×1 Matrix{Int64}:
    1
    2
    =#
    

同理,maxmaximum也是如此。

# && 与 & 区别

在 Julia 中,&&表示短路与(逻辑运算),&表示按位与(按位运算)。而在 Matlab 中,&&表示短路与(逻辑运算),&表示逻辑与,而bitand表示按位与(按位运算)。

# 报错:要求 bool 表达式
1 && 2 
# ERROR: TypeError: non-boolean (Int64) used in boolean context

(1!=0) && (2!=0)
# true

# 按位运算,等价于Matlab的 bitand(1,2)
1 & 2
# 0

同理,在 Julia 中,||表示短路或(逻辑运算),|表示按位或(按位运算)。而在 Matlab 中,||表示短路或(逻辑运算),|表示逻辑或,而bitor才表示按位或(按位运算)。

# / 与 \ 区别

对于标量而言,/表示除法,\表示反向除法。例如:

5/2
# 2.5

5\2
# 0.4

5\2 == 2/5
# true

对于矩阵而言:

  • A / B 表示求解关于 X 的线性方程组 A = X*B。计算结果等同于A*inv(B),但性能更高。

    A = Float64[1 4 5; 3 9 2]
    B = Float64[1 4 2; 3 4 2; 8 7 1]
    
    X = A/B
    #=
    2×3 Matrix{Float64}:
    -0.65   3.75  -1.2
      3.25  -2.75   1.0
    =#
    
    A*inv(B)
    #=
    2×3 Matrix{Float64}:
    -0.65   3.75  -1.2
      3.25  -2.75   1.0
    =#
    
  • A \ B 表示求解关系 X 的线性方程组 A*X = B。计算结果等同inv(A)*B,但性能更高。

    A = [1 0; 1 -2] 
    B = [32; -4]
    
    X = A\B
    #=
    2-element Vector{Float64}:
    32.0
    18.0
    =#
    
    inv(A)*B
    #=
    2-element Vector{Float64}:
    32.0
    18.0
    =#
    

# 向量与行/列矩阵的区别

与 MATLAB 不同,Julia 在概念上就明确区分向量、行矩阵、列矩阵,且它们之间不支持自动转换,需要通过函数来显示转换。

# 向量与矩阵的声明

向量的声明为:

# 向量
v = [1,2,3]
#=
3-element Vector{Int64}:
 1
 2
 3
=#

行矩阵的声明为:

# 行矩阵
r = [1 2 3]
#=
1×3 Matrix{Int64}:
 1  2  3
=#

列矩阵的声明为:

# 列矩阵
c = [1;2;3;;] # 注意:末尾有2个分号
#=
3×1 Matrix{Int64}:
 1
 2
 3
=#

矩阵的声明为:

# 2x3 矩阵
m = [1 2 3; 4 5 6]
#=
2×3 Matrix{Int64}:
 1  2  3
 4  5  6
=#

# 向量与矩阵的转换

向量与矩阵、多维数组之间,可以使用reshapeveccollect等函数来实现相互转换。但是需要用户了解该行为背后究竟是数据拷贝还是引用,以免与预期行为不一致。具体可以参见各函数的帮助。

注,在 Julia 终端中,输入?函数名即可查看该函数的详细说明。

  • reshape转换

    使用reshape可以改变数组维度,值得注意的是,转换前后的两个数组共享相同的底层数据。

    # 向量转矩阵
    v = [1,2,3]
    v2 = reshape(v, 1,3)
    #=
    1×3 Matrix{Int64}:
    1  2  3
    =#
    
    v2[1] = 10
    
    # 由于 v2 与 v 共享相同的底层数据,所以 v 的数据也被改变
    v
    #=
    3-element Vector{Int64}:
    10
      2
      3
    =#
    
  • vec转换

    使用vec可以将数组转为一维向量,值得注意的是,转换前后的两个数组共享相同的底层数据。

    r = [1 2 3]
    r2 = vec(r)
    #=
    3-element Vector{Int64}:
    1
    2
    3
    =#
    
    r2[1]=10
    
    # 由于 r2 与 r 共享相同的底层数据,所以 r 的数据也被改变
    r
    #=
    1×3 Matrix{Int64}:
    10  2  3
    =#
    
  • collect转换

    使用collect可以将集合转为数组,如范围表达式转为向量。值得注意的是,collect会拷贝一份数据。

    x=1:3
    x2=collect(x)
    #=
    3-element Vector{Int64}:
    1
    2
    3
    =#
    
    x2[1]=10
    
    # 由于 x2 是 x 的一份拷贝,所以x2改变,x不受影响
    x 
    # 1:3
    

# 转置、共轭、共轭转置的区别

在 Julia 中,存在共轭转换、转置、共轭等三种情况,包括:

  • 共轭转置:'adjoint
  • 转置:transpose
  • 共轭:conj

# 共轭转置与转置的区别

对于实数矩阵,共轭转置与转置效果相同,例如:

# 实数矩阵
x=[1 2;3 4]
#=
2×2 Matrix{Int64}:
 1  2
 3  4
=#

# 共轭转置
x'
#=
2×2 adjoint(::Matrix{Int64}) with eltype Int64:
 1  3
 2  4
=#

# 转置
transpose(x)
#=
2×2 transpose(::Matrix{Int64}) with eltype Int64:
 1  3
 2  4
=#

对于复数矩阵,共轭转置与转置差异较大,例如:

A = reshape([x + im*x for x in 1:4], 2, 2)
#=
2×2 Matrix{Complex{Int64}}:
 1+1im  3+3im
 2+2im  4+4im
=#

# 共轭转置
A'
#=
2×2 adjoint(::Matrix{Complex{Int64}}) with eltype Complex{Int64}:
 1-1im  2-2im
 3-3im  4-4im
=#

# 转置
transpose(A)
#=
2×2 transpose(::Matrix{Complex{Int64}}) with eltype Complex{Int64}:
 1+1im  2+2im
 3+3im  4+4im
=#

# 共轭转置与共轭的区别

对于标量,共轭转置与共轭效果相同,例如:

x = 1+2im

# 共轭转置
x'
# 1 - 2im

# 共轭
conj(x)
# 1 - 2im

对于矩阵,共轭转置与共轭差异较大,例如:

A = reshape([x + im*x for x in 1:4], 2, 2)
#=
2×2 Matrix{Complex{Int64}}:
 1+1im  3+3im
 2+2im  4+4im
=#

# 共轭转置
A'
#=
2×2 adjoint(::Matrix{Complex{Int64}}) with eltype Complex{Int64}:
 1-1im  2-2im
 3-3im  4-4im
=#

# 共轭
conj(A)
#=
2×2 Matrix{Complex{Int64}}:
 1-1im  3-3im
 2-2im  4-4im
=#

# 拷贝 or 引用

  1. 对于共轭转置,转换后数组与转换前数组,两者共享相同的底层数据。

    A = reshape([x + im*x for x in 1:4], 2, 2)
    #=
    2×2 Matrix{Complex{Int64}}:
    1+1im  3+3im
    2+2im  4+4im
    =#
    
    B = A' # 共轭转置
    #=
    2×2 adjoint(::Matrix{Complex{Int64}}) with eltype Complex{Int64}:
    1-1im  2-2im
    3-3im  4-4im
    =#
    
    B[1,2]=10 # 修改 B 中元素,此时 A 也会被修改
    
    A
    #=
    2×2 Matrix{Complex{Int64}}:
      1+1im  3+3im
    10+0im  4+4im
    =#
    
  2. 对于转置,转换后数组与转换前数组,两者共享相同的底层数据。

    A = reshape([x + im*x for x in 1:4], 2, 2)
    #=
    2×2 Matrix{Complex{Int64}}:
    1+1im  3+3im
    2+2im  4+4im
    =#
    
    B=transpose(A) # 转置
    #=
    2×2 transpose(::Matrix{Complex{Int64}}) with eltype Complex{Int64}:
    1+1im  2+2im
    3+3im  4+4im
    =#
    
    B[1,2]=10 # 修改 B 中元素,此时 A 也会被修改
    
    A
    #=
    2×2 Matrix{Complex{Int64}}:
      1+1im  3+3im
    10+0im  4+4im
    =#
    
  3. 对于共轭,输入是实数还是复数,两者表现不一致,值得注意。

    对于实数共轭,转换后数组与转换前数组,两者共享相同的底层数据。

    x=[1 2 ;3 4]
    #=
    2×2 Matrix{Int64}:
    1  2
    3  4
    =#
    
    y = conj(x) # 实数共轭,此时是数据引用
    #=
    2×2 Matrix{Int64}:
    1  2
    3  4
    =#
    
    y[1,2]=10 # 修改 y 中元素,x 也会被改变
    10
    
    x
    #=
    2×2 Matrix{Int64}:
    1  10
    3   4
    =#
    

    对于复数共轭,转换后数组与转换前数组,不共享底层数据,即数据拷贝。

    x = ComplexF64[1 2; 3 4]
    #=
    2×2 Matrix{ComplexF64}:
    1.0+0.0im  2.0+0.0im
    3.0+0.0im  4.0+0.0im
    =#
    
    y=conj(x) # 复数共轭,此时是数据拷贝
    
    y[1,2]=10 # 修改 y 中元素,x 不会被改变
    
    x
    #=
    2×2 Matrix{ComplexF64}:
    1.0+0.0im  2.0+0.0im
    3.0+0.0im  4.0+0.0im
    =#