多维数组

类似于其它科学计算语言,Julia语言提供了内置的数组。相较于很多科学计算语言都很关注数组在其它容器上的开销。Julia语言并不特别地对待数组。如同其它Julia代码一样,数组基本完全使用Julia本身实现,由编译器本身进行性能优化。同样的,这也使得通过继承 AbstractArray 来定制数组成为可能。 更多的细节,请参照 :ref: 抽象数组接口

数组是一个存在多维网格中的对象集合。通常,数组包含的对象的类型为 Any 。对大多数计算而言,数组对象一般更具体为 Float64Int32

总的来说,不像其它的科学计算语言,Julia不需要为了获得高性能而将程序被写成向量化的形式。Julia的编译器使用类型推断生成优化的代码来进行数组索引,这样的编程风格在没有牺牲性能的同时,可读性更好,编写起来更方便,有时候还会使用更少的内存。

有一些科学计算语言会通过值来传递数组,这在很多情况下很方便,而在 Julia 中,参数将通过引用传递给函数,这使得函数中对于一个数组输入的修改在函数外部是可见的。Julia 的库函数不会修改传递给它的输入。用户写代码时,如果要想做类似的功能,要注意先把输入复制一份儿。

数组

基础函数

函数 说明
eltype(A) A 中元素的类型
length(A) A 中元素的个数
ndims(A) A 有几个维度
size(A) 返回一个元素为 A 的维度的多元组
size(A,n) A 在某个维度上的长度
stride(A,k) 在维度 k 上,邻接元素(在内存中)的线性索引距离
strides(A) 返回多元组,其元素为在每个维度上,邻接元素(在内存中)的线性索引距离
函数 说明
eltype(A) A 中元素的类型
length(A) A 中元素的个数
ndims(A) A 的维数
size(A) 返回一个包含 A 中每个维度元素个数的多元组
size(A,n) A 在某个维度上的大小
indices(A) 返回一个包含 A 中可能的索引的多元组
indices(A,n) 返回一个在 n 维上可能的索引范围
eachindex(A) 一个能够高效地访问每个 A 中的元素的迭代器
stride(A,k) 第``k``维的跨度(相临元素间的索引距离)
strides(A) 返回一个包含每一维度跨度的多元组

构造和初始化

下列函数中调用的 dims... 参数,既可以是维度的单多元组,也可以是维度作为可变参数时的一组值。

函数 描述
Array{type}(dims...) 未初始化的稠密数组
zeros(type, dims...) 指定类型的全 0 数组. 如果未指明 type, 默认为 Float64
zeros(A) 全 0 数组, 元素类型和大小同 A
ones(type, dims...) 指定类型的全 1 数组. 如果未指明 type, 默认为 Float64
ones(A) 全 1 数组, 元素类型和大小同 A
trues(dims...) trueBool 数组
trues(A) trueBool 数组,大小和 A 相同
falses(dims...) falseBool 数组
falses(A) falseBool 数组,大小和 A 相同
reshape(A, dims...) 将数组 A 中的数据按照指定维度排列
copy(A) 复制 A
deepcopy(A) 深度拷贝,递归地复制 A 中的元素
similar(A, element_type, dims...) 属性与输入数组(稠密、稀疏等)相同的未初始化数组,但指明了元素类型和维度。 第二、三参数可省略,省略时默认为 A 的元素类型和维度
reinterpret(type, A) 二进制数据与输入数组相同的数组,但指定了元素类型
rand(dims) 在 [0,1) 上独立均匀同分布的 Float64 类型的随机数组
randn(dims) Float64 类型的独立正态同分布的随机数组,均值为 0 ,标准差为 1
eye(n) n x n 单位矩阵
eye(m, n) m x n 单位矩阵
linspace(start, stop, n) startstop 的由 n 个元素构成的线性向量
fill!(A, x) 用值 x 填充数组 A
fill(x, dims) 创建指定规模的数组, 并使用 x 填充

一维数组(向量)可以通过使用``[A, B, C, ...]``这样的语句来构造。

连接

使用下列函数,可在任意维度连接数组:

Function Description
cat(k, A...) 在第 k 维上连接给定的n维数组
vcat(A...) ``cat(1, A...)``的简写
hcat(A...) ``cat(2, A...)``的简写

传递给这些函数的参数值将被当做只有一个元素的数组

由于连接函数使用的次数很频繁,所以有一些专用的语法来调用它们

表达式 所调用的函数
[A B C ...] hcat
[A, B, C, ...] vcat
[A B; C D; ...] hvcat

hvcat 同时连接第一维 (用分号隔开) 和第二维度 (用空格隔开).

指定类型的数组初始化

指定类型为``T``的数组可以使用``T[A, B, C, ...]``来初始化. 这将会创建一个元素类型为``T``,元素初始化为``A``, B, ``C``等的一维数组。比如``Any[x, y, z]``将创建一个包含任何类型的混合数组。

类似地,连接语句也能通过加前缀来指定元素类型

julia> [[1 2] [3 4]]
1×4 Array{Int64,2}:
 1  2  3  4

julia> Int8[[1 2] [3 4]]
1×4 Array{Int8,2}:
 1  2  3  4

列表推导

列表推导为构造数组提供了一种更加一般,更加强大的方法。它的语法类似于数学中的集合标记法:

A = [ F(x,y,...) for x=rx, y=ry, ... ]

F(x,y,...) 根据变量 x, y 等来求值。这些变量的值可以是任何迭代对象,但大多数情况下,都使用类似于 1:n2:(n-1) 的范围对象,或显式指明为类似 [1.2, 3.4, 5.7] 的数组。它的结果是一个 N 维稠密数组。

下例计算在维度 1 上,当前元素及左右邻居元素的加权平均数:

julia> x = rand(8)
8-element Array{Float64,1}:
 0.843025
 0.869052
 0.365105
 0.699456
 0.977653
 0.994953
 0.41084
 0.809411

julia> [ 0.25*x[i-1] + 0.5*x[i] + 0.25*x[i+1] for i=2:length(x)-1 ]
6-element Array{Float64,1}:
 0.736559
 0.57468
 0.685417
 0.912429
 0.8446
 0.656511

输出的数组类型由所计算出的元素类型决定。显式地控制类型可以通过在列表推导的前面加上类型前缀完成。例如,我们可以这样来使得结果都是单精度的浮点数

Float32[ 0.25*x[i-1] + 0.5*x[i] + 0.25*x[i+1] for i=2:length(x)-1 ]

生成器表达式

列表推导也可以被用不闭合的方括号写出,从而产生一个称为生成器的对象。这个对象可以通过迭代来产生所需的值,而不需要提前为一个数组分配内存。 (参见 man-interfaces-iteration)。 例如下面的表达式会对一列没有分配内存的数求和

julia> sum(1/n^2 for n=1:1000)
1.6439345666815615

在生成器参数列表中有多个维度的时候,需要通过括号来分割各个参数:

julia> map(tuple, 1/(i+j) for i=1:2, j=1:2, [1:4;])
ERROR: syntax: invalid iteration specification

所有在 for 之后通过逗号分割的表达式将被解释成范围。通过增加括号能够使得我们给 map 增加第三个参数:

julia> map(tuple, (1/(i+j) for i=1:2, j=1:2), [1 3; 2 4])
2×2 Array{Tuple{Float64,Int64},2}:
 (0.5,1)       (0.333333,3)
 (0.333333,2)  (0.25,4)

生成器和列表推导的范围可以通过多个``for``关键字对外层范围依赖:

julia> [(i,j) for i=1:3 for j=1:i]
6-element Array{Tuple{Int64,Int64},1}:
 (1,1)
 (2,1)
 (2,2)
 (3,1)
 (3,2)
 (3,3)

在上面发的情况中,结果都会是一维数组

生成的值可以通过 if 关键字过滤

julia> [(i,j) for i=1:3 for j=1:i if i+j == 4]
2-element Array{Tuple{Int64,Int64},1}:
 (2,2)
 (3,1)

索引

索引 n 维数组 A 的通用语法为:

X = A[I_1, I_2, ..., I_n]

其中 I_k 可以是:

  1. 标量
  2. 满足 :, a:b, 或 a:b:c 格式的 Range 对象
  3. 能够选取整个维度的``:或者``Colon()
  4. 任意整数数组,包括空数组 []
  5. 能够输出所在位置为``true``的索引所对应元素的布尔数组

如果所有的索引都是标量,那么结果 X`` 就是 ``A 中的单个元素。不然 ``X``就是一个和索引有相同维度的数组。

例如如果所有的索引都是向量,那么 X``的大小就会是``(length(I_1), length(I_2), ..., length(I_n))X``位于``(i_1, i_2, ..., i_n)``的元素具有``A[I_1[i_1], I_2[i_2], ..., I_n[i_n]]``的值。如果``I_1``被变为一个两维的矩阵,这个矩阵就会给``X``增加一个维度,那么``X``就会是一个``n+1``维的数组,大小为``(size(I_1, 1), size(I_1, 2), length(I_2), ..., length(I_n))。位于``(i_1, i_2, i_3, ..., i_{n+1})``的元素就会有``A[I_1[i_1, i_2], I_2[i_3], ..., I_n[i_{n+1}]]``的值。所有用标量索引的维度的大小会被忽略。比如,A[2, I, 3]``的结果是一个具有 ``size(I)`` 大小的数组。它的第 ``ith 个元素是``A[2, I[i], 3]``。

使用布尔数组``B``通过:func:`find(B) <find>`进行索引和通过向量索引实际上是类似的。它们通常被称作逻辑索引,这将选出那些``B``中值为``true``的元素所在的索引在``A``中的值。一个逻辑索引必须是一个和对应维度有着同样长度的向量,或者是唯一一个和被索引数组的维度以及大小相同的索引。直接使用布尔数组进行索引一般比用:func:`find(B) <find>`进行索引更快。

进一步,多维数组的单个元素可以用``x = A[I]``索引,这里``I`` 是一个 ``CartesianIndex``(笛卡尔坐标)。它实际上类似于一个 整数``n``元组。具体参见下面的:ref:man-array-iteration

``end``关键字是这里比较特殊的一个语法,由于最内层被索引的数组的大小会被确定,它可以在索引的括号中用来表示每个维度最后一个索引。不使用``end``关键字的索引与使用``getindex``一样:

X = getindex(A, I_1, I_2, ..., I_n)

例子:

julia> x = reshape(1:16, 4, 4)
4×4 Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}}:
 1  5   9  13
 2  6  10  14
 3  7  11  15
 4  8  12  16

julia> x[2:3, 2:end-1]
2×2 Array{Int64,2}:
 6  10
 7  11

julia> x[map(ispow2, x)]
5-element Array{Int64,1}:
  1
  2
  4
  8
 16

julia> x[1, [2 3; 4 1]]
2×2 Array{Int64,2}:
  5  9
 13  1

类似于``n:n-1``的空范围有时可以用来表示索引之间的位置。例如``searchsorted``函数使用这个方法来表示在有序数组中没有出现的元素:

julia> a = [1,2,5,6,7];

julia> searchsorted(a, 3)
3:2

赋值

给 n 维数组 A 赋值的通用语法为:

A[I_1, I_2, ..., I_n] = X

其中 I_k 可能是:

  1. 标量
  2. 满足 :, a:b, 或 a:b:c 格式的 Range 对象
  3. 能够选取整个维度的``:或者``Colon()
  4. 任意整数数组,包括空数组 []
  5. 能够输出所在位置为``true``的索引所对应元素的布尔数组

如果 X 是一个数组,它的维度应为 (length(I_1), length(I_2), ..., length(I_n)) ,且 Ai_1, i_2, ..., i_n 处的值被覆写为 X[I_1[i_1], I_2[i_2], ..., I_n[i_n]] 。如果 X 不是数组,它的值被写进所有 A 被引用的地方。

用于索引的布尔值向量与 getindex 中一样(先由 find 函数进行转换)。

索引赋值语法等价于调用 setindex!

setindex!(A, X, I_1, I_2, ..., I_n)

例如:

julia> x = reshape(1:9, 3, 3)
3x3 Array{Int64,2}:
 1  4  7
 2  5  8
 3  6  9

julia> x[1:2, 2:3] = -1
-1

julia> x
3x3 Array{Int64,2}:
 1  -1  -1
 2  -1  -1
 3   6   9

迭代

我们建议使用下面的方法迭代整个数组:

for a in A
    # Do something with the element a
end

for i in eachindex(A)
    # Do something with i and/or A[i]
end

在你需要使用具体的值而不是每个元素的索引的时候,使用第一个方法。在第二种方法里,如果``A``是一个有快速线性索引的数组, i``将是一个``Int`` 类型,否则将会是``CartesianIndex:

A = rand(4,3)
B = view(A, 1:3, 2:3)
julia> for i in eachindex(B)
           @show i
       end
       i = Base.IteratorsMD.CartesianIndex_2(1,1)
       i = Base.IteratorsMD.CartesianIndex_2(2,1)
       i = Base.IteratorsMD.CartesianIndex_2(3,1)
       i = Base.IteratorsMD.CartesianIndex_2(1,2)
       i = Base.IteratorsMD.CartesianIndex_2(2,2)
       i = Base.IteratorsMD.CartesianIndex_2(3,2)

相较``for i = 1:length(A)``,使用``eachindex``更加高效。

数组的特性

如果你写了一个定制的 AbstractArray 类型,你可以用下面的方法声明它有快速线性索引:

Base.linearindexing{T<:MyArray}(::Type{T}) = LinearFast()

这个设置会让 MyArray``(你所定义的数组类型)的 ``eachindex`` 的迭代使用整数类型。如果你没有声明这个特性,那么会默认使用 ``LinearSlow()

向量化的运算符和函数

数组支持下列运算符。逐元素进行的运算,应使用带“点”(逐元素)版本的二元运算符。

  1. 一元: -, +, !
  2. 二元: +, -, *, .*, /, ./, \, .\, ^, .^, div, mod
  3. 比较: .==, .!=, .<, .<=, .>, .>=
  4. 一元布尔值或位运算: ~
  5. 二元布尔值或位运算: &, |, $

有一些运算符在没有``.``运算符的时候,由于有一个参数是标量同样是是逐元素运算的。这些运算符是``*``, +, -,和位运算符。/```` 运算符在分母是标量时也是逐元素计算的。

注意比较运算,在给定一个布尔值的时候,是对整个数组进行的,比如``==``。在逐元素比较时请使用``.``运算符。

Julia为将操作广播至整个数组或者数组和标量的混合变量中,提供了 f.(args...) 这样的兼容语句。这样会使调用向量化的数学操作或者其它运算更加方便。例如 sin.(x)`` 或者 ``min.(x,y)。(广播操作)详见 man-dot-vectorizing

注意 min maxminimum maximum 之间的区别,前者是对多个数组操作,找出各数组对应的的元素中的最大最小,后者是作用在一个数组上找出该数组的最大最小值。

广播

有时要对不同维度的数组进行逐元素的二元运算,如将向量加到矩阵的每一列。低效的方法是,把向量复制成同维度的矩阵:

julia> a = rand(2,1); A = rand(2,3);

julia> repmat(a,1,3)+A
2x3 Array{Float64,2}:
 1.20813  1.82068  1.25387
 1.56851  1.86401  1.67846

维度很大时,效率会很低。Julia 提供 broadcast 函数,它将数组参数的维度进行扩展,使其匹配另一个数组的对应维度,且不需要额外内存,最后再逐元素调用指定的二元函数:

julia> broadcast(+, a, A)
2x3 Array{Float64,2}:
 1.20813  1.82068  1.25387
 1.56851  1.86401  1.67846

julia> b = rand(1,2)
1x2 Array{Float64,2}:
 0.867535  0.00457906

julia> broadcast(+, a, b)
2x2 Array{Float64,2}:
 1.71056  0.847604
 1.73659  0.873631

逐元素的运算符,如 .+.* 将会在必要时进行 broadcasting 。还提供了 broadcast! 函数,可以明确指明目的,而 broadcast_getindexbroadcast_setindex! 函数可以在索引前对索引值做 broadcast 。

并且,``broadcast`` 不仅限于数组(参见函数的文档),它也能用于多元组和并将不是数组和多元组的参数当做“标量”对待。

julia> convert.(Float32, [1, 2])
2-element Array{Float32,1}:
 1.0
 2.0

julia> ceil.((UInt8,), [1.2 3.4; 5.6 6.7])
2×2 Array{UInt8,2}:
 0x02  0x04
 0x06  0x07

julia> string.(1:3, ". ", ["First", "Second", "Third"])
3-element Array{String,1}:
 "1. First"
 "2. Second"
 "3. Third"

实现

Julia 的基础数组类型是抽象类型 AbstractArray{T,N} ,其中维度为 N ,元素类型为 TAbstractVectorAbstractMatrix 分别是它 1 维 和 2 维的别名。

AbstractArray 类型包含任何形似数组的类型, 而且它的实现和通常的数组会很不一样。例如,任何具体的 AbstractArray{T,N} 至少要有 size(A) (返回 Int 多元组), getindex(A,i)getindex(A,i1,...,iN) (返回 T 类型的一个元素), 可变的数组要能 setindex!。 这些操作都要求在近乎常数的时间复杂度或 O(1) 复杂度,否则某些数组函数就会特别慢。具体的类型也要提供类似于 similar(A,T=eltype(A),dims=size(A)) 的方法用来分配一个拷贝。

``DenseArray`` 是``AbstractArray``的一个抽象子类型,它包含了所有的在内存中使用常规形式分配内存,并且也因此能够传递给C和Fortran语言的数组。子类型需要提供``stride(A,k)``方法用以返回第``k``维的间隔:给维度 ``k`` 索引增加 ``1`` 将会给 getindex(A,i) 的第 ``i`` 个索引增加 stride(A,k)。 如果提供了指针的转换函数:func:Base.unsafe_convert(Ptr{T}, A) <unsafe_convert> 那么,内存的分布将会和这些维度的间隔相同。

Array{T,N} 类型是 DenseArray 的特殊实例,它的元素以列序为主序存储(详见 代码性能优化 )。 VectorMatrix 是分别是它 1 维 和 2 维的别名。

SubArrayAbstractArray 的特殊实例,它通过引用而不是复制来进行索引。使用 sub 函数来构造 SubArray ,它的调用方式与 getindex 相同(使用数组和一组索引参数)。 sub 的结果与 getindex 的结果类似,但它的数据仍留在原地。 subSubArray 对象中保存输入的索引向量,这个向量将被用来间接索引原数组。

StridedVectorStridedMatrix 是为了方便而定义的别名。通过给他们传递 ArraySubArray 对象,可以使 Julia 大范围调用 BLAS 和 LAPACK 函数,提高内存申请和复制的效率。

下面的例子计算大数组中的一个小块的 QR 分解,无需构造临时变量,直接调用合适的 LAPACK 函数。

julia> a = rand(10,10)
10×10 Array{Float64,2}:
 0.561255   0.226678   0.203391  0.308912     0.750307  0.235023   0.217964
 0.718915   0.537192   0.556946  0.996234      0.666232  0.509423   0.660788
 0.493501   0.0565622  0.118392  0.493498      0.262048  0.940693   0.252965
 0.0470779  0.736979   0.264822  0.228787      0.161441  0.897023   0.567641
 0.343935   0.32327    0.795673  0.452242      0.468819  0.628507   0.511528
 0.935597   0.991511   0.571297  0.74485      0.84589   0.178834   0.284413
 0.160706   0.672252   0.133158  0.65554       0.371826  0.770628   0.0531208
 0.306617   0.836126   0.301198  0.0224702     0.39344   0.0370205  0.536062
 0.890947   0.168877   0.32002   0.486136      0.096078  0.172048   0.77672
 0.507762   0.573567   0.220124  0.165816      0.211049  0.433277   0.539476

julia> b = view(a, 2:2:8,2:2:4)
4×2 SubArray{Float64,2,Array{Float64,2},Tuple{StepRange{Int64,Int64},StepRange{Int64,Int64}},false}:
 0.537192  0.996234
 0.736979  0.228787
 0.991511  0.74485
 0.836126  0.0224702

julia> (q,r) = qr(b);

julia> q
4×2 Array{Float64,2}:
 -0.338809   0.78934
 -0.464815  -0.230274
 -0.625349   0.194538
 -0.527347  -0.534856

julia> r
2×2 Array{Float64,2}:
 -1.58553  -0.921517
  0.0       0.866567

稀疏矩阵

稀疏矩阵 是其元素大部分为 0 ,并以特殊的形式来节省空间和执行时间的存储数据的矩阵。稀疏矩阵适用于当使用这些稀疏矩阵的表示方式能够获得明显优于稠密矩阵的情况。

列压缩(CSC)存储

Julia 中,稀疏矩阵使用 列压缩(CSC)格式 。Julia 稀疏矩阵的类型为 SparseMatrixCSC{Tv,Ti} ,其中 Tv 是非零元素的类型, Ti 是整数类型,存储列指针和行索引:

type SparseMatrixCSC{Tv,Ti<:Integer} <: AbstractSparseMatrix{Tv,Ti}
    m::Int                  # Number of rows
    n::Int                  # Number of columns
    colptr::Vector{Ti}      # Column i is in colptr[i]:(colptr[i+1]-1)
    rowval::Vector{Ti}      # Row values of nonzeros
    nzval::Vector{Tv}       # Nonzero values
end

列压缩存储便于按列简单快速地存取稀疏矩阵的元素,但按行存取则较慢。把非零值插入 CSC 结构等运算,都比较慢,这是因为稀疏矩阵中,在所插入元素后面的元素,都要逐一移位。

如果你从其他地方获得的数据是 CSC 格式储存的,想用 Julia 来读取,应确保它的序号从 1 开始索引。每一列中的行索引值应该是排好序的。如果你的 SparseMatrixCSC 对象包含未排序的行索引值,对它们进行排序的最快的方法是转置两次。

有时,在 SparseMatrixCSC 中存储一些零值,后面的运算比较方便。 Base 中允许这种行为(但是不保证在操作中会一直保留这些零值)。这些被存储的零被许多函数认为是非零值。 nnz 函数返回稀疏数据结构中存储的元素数目,包括被存储的零。要想得到准确的非零元素的数目,请使用 countnz 函数,它挨个检查每个元素的值(因此它的时间复杂度不再是常数,而是与元素数目成正比)。

构造稀疏矩阵

稠密矩阵有 zeroseye 函数,稀疏矩阵对应的函数,在函数名前加 sp 前缀即可:

julia> spzeros(3,5)
3x5 sparse matrix with 0 Float64 entries:

julia> speye(3,5)
3x5 sparse matrix with 3 Float64 entries:
        [1, 1]  =  1.0
        [2, 2]  =  1.0
        [3, 3]  =  1.0

sparse 函数是比较常用的构造稀疏矩阵的方法。它输入行索引 I ,列索引向量 J ,以及非零值向量 Vsparse(I,J,V) 构造一个满足 S[I[k], J[k]] = V[k] 的稀疏矩阵:

julia> I = [1, 4, 3, 5]; J = [4, 7, 18, 9]; V = [1, 2, -5, 3];

julia> S = sparse(I,J,V)
5x18 sparse matrix with 4 Int64 entries:
        [1 ,  4]  =  1
        [4 ,  7]  =  2
        [5 ,  9]  =  3
        [3 , 18]  =  -5

sparse 相反的函数为 findn ,它返回构造稀疏矩阵时的输入:

julia> findn(S)
([1,4,5,3],[4,7,9,18])

julia> findnz(S)
([1,4,5,3],[4,7,9,18],[1,2,3,-5])

另一个构造稀疏矩阵的方法是,使用 sparse 函数将稠密矩阵转换为稀疏矩阵:

julia> sparse(eye(5))
5x5 sparse matrix with 5 Float64 entries:
        [1, 1]  =  1.0
        [2, 2]  =  1.0
        [3, 3]  =  1.0
        [4, 4]  =  1.0
        [5, 5]  =  1.0

可以使用 densefull 函数做逆操作。 issparse 函数可用来检查矩阵是否稀疏:

julia> issparse(speye(5))
true

稀疏矩阵运算

稠密矩阵的算术运算也可以用在稀疏矩阵上。对稀疏矩阵进行赋值运算,是比较费资源的。大多数情况下,建议使用 findnz 函数把稀疏矩阵转换为 (I,J,V) 格式,在非零数或者稠密向量 (I,J,V) 的结构上做运算,最后再重构回稀疏矩阵。

稠密矩阵和稀疏矩阵函数对应关系

接下来的表格列出了内置的稀疏矩阵的函数, 及其对应的稠密矩阵的函数。通常,稀疏矩阵的函数,要么返回与输入稀疏矩阵 S 同样的稀疏度,要么返回 d 稠密度,例如矩阵的每个元素是非零的概率为 d

详见可以标准库文档的 Sparse Matrices 章节。

稀疏矩阵 稠密矩阵 说明
spzeros(m,n) zeros(m,n) 构造 m x n 的全 0 矩阵 (spzeros(m,n) 是空矩阵)
spones(S) ones(m,n) 构造的全 1 矩阵 与稠密版本的不同, spones 的稀疏 度与 S 相同
speye(n) eye(n) 构造 m x n 的单位矩阵
full(S) sparse(A) 转换为稀疏矩阵和稠密矩阵
sprand(m,n,d) rand(m,n) 构造 m-by-n 的随机矩阵(稠密度为 d ) 独立同分布的非零元素在 [0, 1] 内均匀分布
sprandn(m,n,d) randn(m,n) 构造 m-by-n 的随机矩阵(稠密度为 d ) 独立同分布的非零元素满足标准正 态(高斯)分布
sprandn(m,n,d,X) randn(m,n,X) 构造 m-by-n 的随机矩阵(稠密度为 d ) 独立同分布的非零元素满足 X 分 布。(需要 Distributions 扩展包)
sprandbool(m,n,d) randbool(m,n) 构造 m-by-n 的随机矩阵(稠密度为 d ) ,非零 Bool``元素的概率为 *d* (``randboold =0.5 )