两种不同类型的数组数组

use*_*278 4 arrays julia

我对不同类型的数组数组感到困惑。考虑这两个例子

a = Array{Float64}[]
push!(a,[1, 2])
push!(a,[3, 4])
push!(a,[1 2; 3 4])

b = Array[[1.0, 2.0], [3.0,4.0], [1.0 2.0; 3.0 4.0]]

Run Code Online (Sandbox Code Playgroud)

我不确定如何ab不同。假设我打算对aor 中的b每个元素运行一个 for 循环,并将每个元素乘以 2。也就是说,

for i in 1:3 a[i] = a[i]*2 end

for i in 1:3 b[i] = b[i]*2 end
Run Code Online (Sandbox Code Playgroud)

我分别为两条线的运行时间计时,但它们同样快。是ab一样吗?如果是这样,为什么a甚至存在?它看起来相当复杂,因为typeof(a)产生“Array{Array{Float64,N} where N,1}”。where在这里做什么?

Bog*_*ski 8

两个ab是矢量,但它们允许不同类型的元件。你可以通过写来检查这一点:

julia> typeof(a)
Array{Array{Float64,N} where N,1}

julia> typeof(b)
Array{Array,1}
Run Code Online (Sandbox Code Playgroud)

现在Array是带两个参数的参数类型。第一个参数是它允许的元素类型。第二个参数是维度。您可以看到,在这两种情况下,维数都1意味着ab都是向量。您还可以使用以下ndims功能检查它:

julia> ndims(a)
1

julia> ndims(b)
1
Run Code Online (Sandbox Code Playgroud)

第一个参数是允许的元素类型。在a它的情况下,Array{Float64,N} where N而在b只是Array打印的情况下。在我解释如何阅读它们之前,请注意可以使用该eltype函数提取第一个参数:

julia> eltype(a)
Array{Float64,N} where N

julia> eltype(b)
Array
Run Code Online (Sandbox Code Playgroud)

你可以看到,无论是ab允许Array存储。首先让我解释一下如何阅读Array{Float64, N} where N。这意味着a允许存储Float64任何维度的数组。实际上,您可以像这样Array{Float64}以更短的方式编写,因为您可以检查:

julia> (Array{Float64,N} where N) === Array{Float64}
true
Run Code Online (Sandbox Code Playgroud)

原因是如果您不对尾部参数设置限制,则可以在语法中删除它。该where N部分是对参数的限制。在这种情况下,对第二个参数没有限制。

现在我们可以转向b. 您会看到它eltype只是Array,因此两个参数都被删除,因此如上所述对它们没有限制。所以和你在这里看到Array的一样Array{T, N} where {T,N}

julia> (Array{T, N} where {T,N}) === Array
true
Run Code Online (Sandbox Code Playgroud)

所以区别在于a可以存储任意维度的数组但必须具有Float64元素类型,而b可以存储任意维度和任意元素类型的数组。在这种情况下,这种区别对性能没有影响,但会影响a和 中可以存储的内容b。这里有些例子。

在这种情况下,它们的工作方式与您尝试Int在其中存储 an 相同,但它们仅允许使用数组:

julia> a[1] = 1
ERROR: MethodError: Cannot `convert` an object of type

julia> b[1] = 1
ERROR: MethodError: Cannot `convert` an object of type
Run Code Online (Sandbox Code Playgroud)

但在这里他们有所不同:

julia> a[1] = ["a"]
ERROR: MethodError: Cannot `convert` an object of type String to an object of type Float64

julia> b[1] = ["a"]
1-element Array{String,1}:
 "a"

julia> a
3-element Array{Array{Float64,N} where N,1}:
 [1.0, 2.0]
 [3.0, 4.0]
 [1.0 2.0; 3.0 4.0]

julia> b
3-element Array{Array,1}:
 ["a"]
 [3.0, 4.0]
 [1.0 2.0; 3.0 4.0]
Run Code Online (Sandbox Code Playgroud)

如您所见,您可以存储一个Stringin数组b,但不允许将其存储在a.

两个额外的评论(两个主题都有点复杂,所以我省略了细节,但只是给你提示正在发生的事情):

  1. 定义数组时可以不指定数组的元素类型。在这种情况下,Julia 将自动选择其元素类型:
julia> [[1.0, 2.0], [3.0,4.0], [1.0 2.0; 3.0 4.0]]
3-element Array{Array{Float64,N} where N,1}:
 [1.0, 2.0]
 [3.0, 4.0]
 [1.0 2.0; 3.0 4.0]
Run Code Online (Sandbox Code Playgroud)
  1. 数组元素类型选择对性能的影响取决于以下事实:

    1. 如果类型是抽象的(可以通过isabstracttype; 这会影响编译器做出的类型推断),
    2. 如果它是位类型(可以通过检查isbitstype;这会影响存储布局),
    3. 如果元素类型是Union(可以更有效地处理小联合)。

在您的情况下,两种元素类型都是抽象的和非位的,因此性能是相同的。