Engee 文档

Engee 中的数组、向量和矩阵

导言

在*Engee*中,数组、向量和矩阵用于处理数据、参数和复杂结构。这些结构由Julia 语言实现,可以高效地存储和处理数值信息,包括计算结果、信号和模型参数。本文将讨论它们各自的特点。

在 Julia 中,数组、矢量和矩阵的元素编号以 "1 "开头,而不是像其他语言那样以 "0 "开头。最后一个元素的索引为 "end"。这与数学的传统是一致的,数学的索引也是从 1 开始。例如,数组 a = [1, 2, 3] 的第一个元素用 a[1] 访问,最后一个元素用 `a[end]`访问。详见下文

数组*是一种通用的多维容器,可以包含任何类型的元素。Julia 中的数组支持任意维数,是存储和处理数据的多功能工具:

A = rand(2, 2, 3)
输出
2×2×3 Array{Float64, 3}:
[:, :, 1] =
 0.159525  0.787948
 0.358068  0.124023

[:, :, 2] =
 0.228296  0.292929
 0.712896  0.0253828

[:, :, 3] =
 0.3547    0.837655
 0.474441  0.201402

数组有动态和静态之分:

  • *动态数组*是在程序执行过程中其大小可能发生变化的数组。这些数组存储在内存中,可能会进行扩展,这使得它们更加灵活,但对于计算密集型任务来说,却不是最佳选择。

    例如

    dynamic_array = [1, 2, 3]
    dynamic_array[2] = 5 # Присваивание значения
    push!(dynamic_array, 4) # Добавление элемента
    deleteat!(dynamic_array, 3) # Удаление элемента с индексом 3
    输出
    4-element Vector{Int64}:
     1
     5
     3
     4
  • *静态数组*是具有固定大小的数组,大小在创建阶段设定。它们以连续数据块的形式存储在内存中,这样可以最大限度地减少内存管理开销,从而更快地执行操作。

    当静态数组的大小小于 100-200 个元素时,其效率较高。如果大小大于 100-200 个元素,则通常使用动态数组。

    在 Julia 中,静态数组由 StaticArrays.jl 包提供。因此,要使用静态数组,需要使用 using StaticArrays 命令连接 该软件包。

    示例

    using StaticArrays
    static_array = @SVector [1, 2, 3]
    输出
    3-element SVector{3, Int64} with indices SOneTo(3):
     1
     2
     3

    代码中使用了一个宏脚注:@SVector,用于创建一个固定大小的静态一维数组(向量)。静态数组还有其他有用的宏:

    静态数组宏_。
    • @SVector - 创建一个固定大小的不可变静态向量。例如`@SVector [1, 2, 3]`。

    • @MVector - 创建一个固定大小的可变静态向量。示例`@MVector [1, 2, 3]`.

    • @SMatrix - 创建一个固定大小的可变静态矩阵。示例`@SMatrix [1 2; 3 4]`.

    • @MMatrix - 创建一个固定大小的可变静态矩阵。示例`@MMatrix [1 2; 3 4]`.

    • @SizedArray - 将普通数组转换为固定大小的静态数组。示例`@SisedArray rand(2, 2)`.

    • @SArray - 创建一个固定大小的普通静态数组,可以是向量、矩阵或高维数组。示例`@SArray rand(2, 2, 2, 2)`.

    • @MArray - 创建一个通用的可变静态数组。示例`@MArray rand(2, 2, 2, 2)`.

    • @StaticArray - 一个通用宏,用于创建任意形状的不可变数组。示例`@StaticArray rand(2, 2, 2)`.

    • @MutableStaticArray 是创建可变静态数组的通用宏。示例`@MutableStaticArray rand(2, 2)`.

    • @zeros - 创建一个充满 0 的静态数组。示例`@zeros(SVector, 3)` 创建一个包含三个零的向量。

    • @ones - 创建一个充满 1 的静态数组。示例`@ones(SMatrix, 2, 2)` 创建一个 2×2 的 1 矩阵。

    • @fill - 创建一个充满给定值的静态数组。示例@fill(SVector,3,42)`创建一个由三个元素组成、值为 42 的矢量。

    • @static - 通过应用静态数组的属性,在编译阶段优化代码块的执行。

      示例

      @static if length(SVector(1, 2, 3)) == 3
      println("Размер 向量а равен 3")
      end

与 C++ 不同,Julia 中的数组可以存储不同类型的元素。如果元素类型可以简化为一种通用类型(例如 "有理数 "和 "复数"),Julia 将自动执行类型转换。例如

[1//2, 3 + 4im]  # Автоматически преобразуется в 2-element Vector{Complex{Rational{Int64}}}:

如果元素类型无法还原为一种通用类型(例如数字和字符串),Julia 会将数组转换为 Any 类型,即所有类型的联合:

[1, "строка"]  # Тип массива — Vector{Any}

这使得 Julia 中的数组变得灵活,但值得注意的是,使用 Any 可能会降低性能,因为编译器无法针对特定类型优化代码。更多信息,请参见Conversion and Promotion

矢量*是一个一维数组,是使用索引访问的元素序列。在 Julia 中,矢量可以创建为*矢量列*或*矢量字符串*,但它们的语法和数据类型有所不同:

  • 列向量使用逗号或列条目创建:

    v = [1, 2, 3]  # Вектор-столбец

    v = [1
         2
         3]  # Вектор-столбец
    输出
    3-element Vector{Int64}:
     1
     2
     3
  • Julia 没有单独的矢量字符串类型。取而代之的是,数字字符串被表示为维度为 1 × N 的矩阵:

    r = [1 2 3]  # Матрица 1 × 3
    输出
    1×3 Matrix{Int64}:
     1  2  3

在 Julia 中,数组中的分隔符定义了数组的结构:

  • 逗号 (,) 用于创建*向量*(一维数组)。元素之间用逗号隔开:

    v = [1, 2, 3]  # Вектор-столбец
  • 分号 (;) 用于创建矩阵(二维数组)。它用于分隔字符串,类似于 vcat 函数:

    m = [1 2 3; 4 5 6]  # Матрица 2 × 3

矩阵(Matrix)是一个二维数组,代表一个按行和列排列的数字或其他对象的表格。在 Julia 中,矩阵是以二维数组的形式创建的:

M = [1 2 3; 4 5 6]
输出
2×3 Matrix{Int64}:
 1  2  3
 4  5  6

在 Julia 中,矢量和矩阵的分离可以有效地组织内存中的数据,这对快速数值计算非常重要。矢量使用一维存储,因此更容易处理数据序列,而矩阵则以二维形式组织,因此更容易执行线性代数(乘法和转置)。这种分离有助于优化缓存内存和 CPU 资源的使用,提高计算效率。

数组、矢量和矩阵之间的区别

维度:

  • 数组是具有任意维数的容器。数组有任意维数,例如,size(A) 可以返回 (2, 2, 3)。

  • 向量是一维数组。向量总是一维的,函数 size(v) 返回元组 (n,),其中 n 是向量的长度。

  • 矩阵是一个二维数组。矩阵的维数为二,size(M) 返回`(n, m)`元组,其中`n`是行数,`m`是列数。

元组是一种不可变的数据结构,可以包含不同类型的多个元素。在 Julia 中,元组用于表示逻辑上相关但无需修改的值。例如,函数`size()`的结果总是以元组的形式返回。

与向量和矩阵不同,元组不是数组,也不是用来执行算术运算的。它有固定数量的元素和不可变的结构,因此在从函数返回多个值或传递参数时非常有用。

  1. 实施特点

    • 处理数组的方法和函数适用于向量和矩阵。不过,每种类型的数据都有不同的优化算法。

    • 在 Julia 中,矢量和矩阵是数组的特例,其中矢量的维度为 "1",矩阵的维度为 "2"。

  2. 初始化和语法

    • 可通过 Array 函数或使用生成器(表达式为"[…​ for …​]")创建任意维数的数组。例如,对于 Array:

      A = Array{Float64}(undef, 2, 2, 3)

      这里的 undef 是一个关键字,用于创建一个数组而不初始化元素。这意味着将为数组分配内存,但其元素的值将保持未定义(可能是随机的)。

      使用生成器的示例

      array = [i^2 for i in 1:5] # Каждый элемент массива – квадрат числа от 1 до 5
    • 以一维数组的形式创建向量,使用逗号枚举元素:

      v = [1, 2, 3]
    • 矩阵以分号分隔行 (;),行中的元素以空格或制表符分隔:

      M = [1 2 3; 4 5 6]
  3. 内存存储:

    • 具有大量维度的阵列使用更通用的存储方法,这会增加操作的开销。


上述差异形成了特定的应用领域:

  • 阵列用于模拟更复杂的数据:三维模型、图像阵列或多维时间序列。

  • 矢量最常用于一维数据:时间序列、坐标、信号。

  • 矩阵表示二维结构:图像、表格、线性方程组。

处理数组、矢量和矩阵的基本功能

Julia 提供了大量处理数组(包括矢量和矩阵)的函数。有关这些函数及其签名的更多信息,请访问Arrays

标有`*`的函数不是标准库的一部分。要使用它们,请安装相应的 Julia 软件包:

import Pkg
Pkg.add("имя пакета")

导入 "和 "使用 "操作符以及软件包名称可用于访问此类函数的元素。更多信息,请访问使用 Julia 软件包

以下是基本函数列表,附有简要说明和示例:

创建
创造

功能名称

说明

示例

zeros.

创建一个元素等于零的数组。

创建对象的类型取决于传递的参数:一维数组(向量)、二维数组(矩阵)或多维数组。

[源代码,julia].

zeros(3)
zeros(2, 2)
zeros(2, 2, 3)

这里

  • zeros(3) - 创建一个向量 [0.0, 0.0, 0.0, 0.0].

  • zeros(2, 2) - 创建一个 2x2 矩阵

  • zeros(2, 2, 3) - 创建一个三维数组

ones - 创建一个元素相等的数组。

创建元素等于 1 的数组。

创建对象的类型取决于传递的参数:一维数组(向量)、二维数组(矩阵)或多维数组。

[源代码,julia].

ones(3)
ones(2, 2)
ones(2, 2, 3)

这里

  • ones(3)` - 创建一个向量 [1.0, 1.0, 1.0, 1.0](三个元素,都等于 1.0)。

  • ones(2, 2)` - 创建一个 2x2 矩阵:

    2×2 Matrix{Float64}:
     1.0  1.0
     1.0  1.0
  • ones(2, 2, 3)` - 创建一个大小为 2x2x3 的三维数组,其中所有元素都等于 1.0:

    2×2×3 Array{Float64, 3}:
    [:, :, 1] =
     1.0  1.0
     1.0  1.0
    
    [:, :, 2] =
     1.0  1.0
     1.0  1.0
    
    [:, :, 3] =
     1.0  1.0
     1.0  1.0

rand`。

创建一个数组,其中包含在"[0, 1) "区间内均匀分布的随机数。创建对象的类型取决于传递的参数:一维数组(向量)、二维数组(矩阵)或多维数组。

[源代码,julia].

rand(3)
rand(2, 2)
rand(2, 2, 3)

这里

  • rand(3) - 创建一个包含三个随机数的向量,例如`[0.574, 0.225, 0.639]`。

    3-element Vector{Float64}:
     0.5741275064461032
     0.2253528689201394
     0.6398495562276317
  • rand(2, 2) - 创建一个充满随机数的 2x2 矩阵,例如:

    2×2 Matrix{Float64}:
     0.526635  0.885571
     0.674019  0.869255
  • rand(2, 2, 3) - 创建一个大小为 2x2x3 的三维数组,其中的元素为随机数,例如

    2×2×3 Array{Float64, 3}:
    [:, :, 1] =
     0.300142  0.594199
     0.125753  0.834848
    
    [:, :, 2] =
     0.707155  0.859128
     0.296165  0.0470918
    
    [:, :, 3] =
     0.220695  0.124332
     0.217407  0.616591

填充

创建一个填充指定值的数组。创建对象的类型取决于传递的参数:一维数组(向量)、二维数组(矩阵)或多维数组。

[源代码,julia].

fill(7, 3)
fill(5, 2, 2)
fill(75, 2, 2, 3)

这里:

  • fill(7, 3) - 创建一个包含三个元素的向量,其中每个元素都是 7,例如 [7, 7, 7, 7]

  • fill(5, 2, 2, 2) - 创建一个 2x2 矩阵,填充值为 5:

    2×2 Matrix{Int64}:
     5  5
     5  5
  • fill(75, 2, 2, 2, 3) - 创建一个 2x2x3 的三维数组,其中每个元素都等于 75

    2×2×3 Array{Int64, 3}:
    [:, :, 1] =
     75  75
     75  75
    
    [:, :, 2] =
     75  75
     75  75
    
    [:, :, 3] =
     75  75
     75  75

收集

通过转换给定的范围或迭代对象创建数组。创建对象的类型取决于所使用的输入。

[源代码,julia].

collect(1:3)
collect(reshape(1:4, 2, 2))
collect(reshape(1:12, 2, 2, 3))

这里:

  • collect(1:3) - 将范围 1:3 转换为向量 [1, 2, 3]

  • collect(reshape(1:4, 2, 2)) - 将范围 1:4 转换为 2x2 矩阵:

    2×2 Matrix{Int64}:
     1  3
     2  4
  • collect(reshape(1:12, 2, 2, 3)) - 将范围 1:12 转换为 2x2x3 的三维数组:

    2×2×3 Array{Int64, 3}:
    [:, :, 1] =
     1  3
     2  4
    
    [:, :, 2] =
     5  7
     6  8
    
    [:, :, 3] =
      9  11
     10  12
结构变化
Structure change

功能名称

说明

示例

push!"。

在一维数组(向量)的末尾添加一个元素。仅适用于可修改(动态)数组。

末尾索引也可用于添加元素 (数组索引).

[源代码,julia].

v = [1, 2, 3]
push!(v, 4)

m = reshape(1:6, 2, 3)
# push! нельзя применить к матрице или многомерному массиву.

这里:

  • v = [1, 2, 3] - 创建一个向量 [1, 2, 3]

  • push!(v, 4) - 将元素 4 添加到向量的末尾。操作完成后`[1, 2, 3, 4]`.

  • push!` 不能应用于 m 矩阵或多维数组,因为它们有固定的大小,需要改变数据结构来添加元素(系统将产生错误 MethodError: no method matching push!)。

pop!`。

从一维数组(向量)中删除并返回最后一个元素。仅适用于可修改(动态)数组。

[源代码,julia].

v = [1, 2, 3, 4]
last_element = pop!(v)

m = reshape(1:6, 2, 3)
# pop! нельзя применить к матрице или многомерному массиву.

这里

  • v = [1, 2, 3, 4] - 创建一个向量 [1, 2, 3, 4]

  • last_element = pop!(v) - 删除向量的最后一个元素(4)并返回。操作后,v 变为 [1, 2, 3],变量 last_element 等于 4

  • pop!` 不能应用于 m 矩阵或多维数组,因为它们的大小是固定的(系统将产生错误 MethodError: no method matching pop!)。

insert!.

在一维数组(向量)的指定位置插入一个元素。仅适用于可修改(动态)数组。

[源代码,julia].

v = [1, 2, 4, 5]
insert!(v, 3, 3)

m = reshape(1:6, 2, 3)
# insert! нельзя применить к матрице или многомерному массиву.

这里

  • v = [1, 2, 4, 5] - 创建一个向量`[1, 2, 4, 5]`。

  • insert!(v, 3, 3, 3) - 将元素 3 插入索引为 3 的位置。操作后,v 变为`[1, 2, 3, 4, 5]`。

  • insert!` 不能用于 m 矩阵或多维数组,因为它们的结构是固定的,不支持动态变化。

删除

从一维数组(向量)中删除指定索引处的元素。仅适用于可修改(动态)数组。

[源代码,julia].

v = [1, 2, 3, 4, 5]
deleteat!(v, 3)

m = reshape(1:6, 2, 3)
# deleteat! нельзя применить к матрице или многомерному массиву.

这里

  • v = [1, 2, 3, 4, 5] - 创建一个向量 [1, 2, 3, 4, 5]

  • deleteat!(v, 3) - 从向量中删除索引为 3 的元素(值 3)。操作后,v 变为`[1, 2, 4, 5]`。

  • deleteat! 不能应用于 m 矩阵或多维数组,因为它们的结构是固定的,不支持删除元素(系统将产生错误 MethodError: no method matching deleteat!)。

使用维数_
使用尺寸

功能名称

说明

示例

size.

以元组形式返回数组、矩阵或向量的大小,其中每个值都对应特定维度的大小。

[源代码,朱莉娅].

v = [1, 2, 3]
size(v)

m = reshape(1:6, 2, 3)
size(m)

a = zeros(2, 2, 3)
size(a)

这里

  • v = [1, 2, 3] - 创建一个向量 [1, 2, 3]

  • size(v) - 返回元组 (3,),其中 3 是向量的长度。

  • m = reshape(1:6, 2, 3) - 创建一个 2x3 矩阵:

    2×3 reshape(::UnitRange{Int64}, 2, 3) with eltype Int64:
     1  3  5
     2  4  6
  • size(m) - 返回一个元组`(2, 3)`,其中`2`是行数,`3`是列数。

  • a = zeros(2, 2, 3) - 创建一个大小为 2x2x3 的三维数组,数组中为零。

  • size(a) - 返回与数组各维度大小相对应的元组 (2, 2, 3)

resize!.

改变一维数组(向量)的大小。如果新的大小大于当前的大小,新的元素将以默认值 `0.0`初始化。如果小于当前大小,数组将被修剪为指定大小。

[源代码,julia].

v = [1, 2, 3]
resize!(v, 5)
resize!(v, 2)

m = reshape(1:6, 2, 3)
# resize! нельзя применить к матрице или многомерному массиву.

这里

  • v = [1, 2, 3] - 创建向量 [1, 2, 3]

  • resize!(v, 5) - 通过添加数值为 0.0 的元素,将向量的大小增加到 5。操作后,v 变为`[1, 2, 3, 0.0, 0.0]`。

  • resize!(v, 2) - 将向量的大小减小为 2。操作后,v 变为 [1,2]

  • resize! 不能应用于 m 矩阵或多维数组,因为它们的结构是固定的(系统将产生错误 MethodError: no method matching resize!)。

长度

返回数组、向量或矩阵中元素的总数,与它们的维数无关。

[源代码,julia].

v = [1, 2, 3]
length(v)

m = reshape(1:6, 2, 3)
length(m)

a = zeros(2, 2, 3)
length(a)

这里

  • v = [1, 2, 3] - 创建一个向量`[1, 2, 3]`。

  • length(v) - 返回 3,因为向量包含三个元素。

  • m = reshape(1:6, 2, 3) - 创建一个 2x3 矩阵:

    2×3 reshape(::UnitRange{Int64}, 2, 3) with eltype Int64:
     1  3  5
     2  4  6
  • length(m) - 返回 6 因为矩阵包含 6 个元素(行列的乘积)。

  • a = zeros(2, 2, 3) - 创建大小为 2x2x3 的三维数组。

  • length(a) - 返回 12,因为数组包含 `12`个元素(所有维度大小的乘积)。

ndims.

返回数组、向量或矩阵的维数。

[源代码,julia].

v = [1, 2, 3]
ndims(v)

m = reshape(1:6, 2, 3)
ndims(m)

a = zeros(2, 2, 3)
ndims(a)

这里

  • v = [1, 2, 3] - 创建一个向量 [1, 2, 3]

  • ndims(v) - 返回 1,因为向量只有一个维度。

  • m = reshape(1:6, 2, 3) - 创建一个 2x3 矩阵:

    2×3 reshape(::UnitRange{Int64}, 2, 3) with eltype Int64:
     1  3  5
     2  4  6
  • ndims(m) - 返回 2 因为矩阵有两个维度(行和列)。

  • a = zeros(2, 2, 3) - 创建一个大小为 2x2x3 的三维数组。

  • ndims(a) - 返回 3,因为数组有三个维度。

reshape.

改变数组、矩阵或向量的维度,将其转换为具有指定行数和列数的新数组。新数组的元素数必须与原始数组的元素数一致。

v = [1, 2, 3, 4, 5, 6]
m = reshape(v, 2, 3)

a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
b = reshape(a, 3, 3)

c = reshape(a, 1, 9)

这里:

  • v = [1, 2, 3, 4, 5, 6] - 创建一个包含 6 个元素的向量。

  • reshape(v, 2, 3) - 将向量转换为包含元素的大小为 2x3 的矩阵:

    2×3 Matrix{Int64}:
     1  3  5
     2  4  6
  • a = [1, 2, 3, 4, 5, 6, 7, 8, 9] - 创建一个包含 9 个元素的向量。

  • reshape(a, 3, 3) - 将向量转换为一个 3x3 矩阵:

    3×3 Matrix{Int64}:
     1  4  7
     2  5  8
     3  6  9
  • reshape(a, 1, 9) - 将向量转换为长度为 9 个元素的字符串:

    1×9 Matrix{Int64}:
     1  2  3  4  5  6  7  8  9
线性代数
线性代数

函数名

说明

示例

转置

返回行列互换的数组或矩阵。对于一维数组(向量),结果取决于其方向。

[源代码,julia].

v = [1, 2, 3]
vt = transpose(v)

m = [1 2; 3 4; 5 6]
mt = transpose(m)

这里

  • v = [1, 2, 3] - 创建列向量 [1 2 3]

  • transpose(v) - 对向量进行转置,将其转换为字符串向量:

    1×3 transpose(::Vector{Int64}) with eltype Int64:
     1  2  3
  • m = [1 2; 3 4; 5 6] - 创建一个 3x2 矩阵:

    3×2 Matrix{Int64}:
     1  2
     3  4
     5  6
  • transpose(m) - 将矩阵转置,变成一个 2x3 矩阵:

    2×3 transpose(::Matrix{Int64}) with eltype Int64:
     1  3  5
     2  4  6

*det.

计算正方形矩阵的行列式。它是 LinearAlgebra 软件包的一部分(需要安装软件包)。

行列式是一个标量,用于描述矩阵的特性(如可逆性)。

m1 = [2 3; 1 4]
det(m1)

m2 = [1 2 3; 4 5 6; 7 8 10]
det(m2)

m3 = [0 1; 2 3]
det(m3)

此处:

  • m1 = 创建了一个 `2x2 矩阵:

    2×2 Matrix{Int64}:
     2  3
     1  4
  • det(m1) - 返回 5.0,因为行列式是用 2×2 矩阵的公式计算的 ((2*4)-(3*1)=8-3=5)。

  • m2 = [1 2 3; 4 5 6; 7 8 10] - 创建一个 3x3 矩阵:

    3×3 Matrix{Int64}:
     1  2   3
     4  5   6
     7  8  10
  • det(m2) - 返回`-3.0`,因为它是通过拉普拉斯分解或其他算法计算的较大矩阵。

  • m3 = [0 1; 2 3] - 创建一个 2x2 矩阵:

    2×2 Matrix{Int64}:
     0  1
     2  3
  • det(m3) - 返回 -2.0,因为行列式等于:(0*3) - (1*2) = 0-2 = -2).

inv.

计算正方形矩阵的逆矩阵。逆矩阵只适用于行列式不为零的矩阵,即可逆矩阵。

即使源矩阵的值是整数("矩阵{Int64}"),"inv "函数也会返回一个 "矩阵{Float64}"类型的逆矩阵。

[源,julia]。

m1 = [2 3; 1 4]
inv(m1)

m2 = [1 2 3; 0 1 4; 5 6 0]
inv(m2)

m3 = [1 2; 3 4]
inv(m3)

这里:

  • m1 = [2 3; 1 4] 创建一个 2x2 矩阵:

    2×2 Matrix{Int64}:
     2  3
     1  4
  • inv(m1) - 返回逆矩阵:

    2×2 Matrix{Float64}:
      0.8  -0.6
     -0.2   0.4
  • m2 = [1 2 3; 0 1 4; 5 6 0] - 创建一个 3x3 矩阵:

    3×3 Matrix{Int64}:
     1  2  3
     0  1  4
     5  6  0
  • inv(m2) - 返回逆矩阵:

    3×3 Matrix{Float64}:
     -24.0   18.0   5.0
      20.0  -15.0  -4.0
      -5.0    4.0   1.0
  • m3 = [1 2; 3 4] - 创建一个 2x2 矩阵:

    2×2 Matrix{Int64}:
     1  2
     3  4
  • inv(m3) - 返回逆矩阵:

    2×2 Matrix{Float64}:
     -2.0   1.0
      1.5  -0.5

*eigvals / *eigvecs.

计算矩阵的特征值和向量。例如

  • eigvals(m) - 返回矩阵 m 的特征值。

  • eigvecs(m) - 返回矩阵 m 的特征向量。

[源代码,julia].

m1 = [4 1; 2 3]
eigvals(m1)
eigvecs(m1)

m2 = [1 2 3; 4 5 6; 7 8 9]
eigvals(m2)
eigvecs(m2)

这里:

  • m1 = [4 1; 2 3] - 创建一个 2x2 矩阵:

    2×2 Matrix{Int64}:
     4  1
     2  3
  • eigvals(m1) - 返回特征值:

    2-element Vector{Float64}:
     2.0
     5.0
  • eigvecs(m1) - 返回特征向量:

    2×2 Matrix{Float64}:
     -0.447214  0.707107
      0.894427  0.707107
  • m2 = [1 2 3; 4 5 6; 7 8 9] - 创建一个 3x3 矩阵:

    3×3 Matrix{Int64}:
     1  2  3
     4  5  6
     7  8  9
  • eigvals(m2) - 返回特征值:

    3-element Vector{Float64}:
     -1.1168439698070416
     -9.759184829871139e-16
     16.116843969807043
  • eigvecs(m2) - 返回特征向量:

    3×3 Matrix{Float64}:
     -0.78583     0.408248  -0.231971
     -0.0867513  -0.816497  -0.525322
      0.612328    0.408248  -0.818673

norm`。

计算向量或矩阵的规范。

常模是衡量向量或矩阵 "大小 "的数字特征。默认情况下,计算的是欧氏常模。

v = [3, 4]
norm(v)

m = [1 2; 3 4]
norm(m)

norm(v, 1) # 3 + 4 = 7.0
norm(m, Inf) #√30 ≈ 5.477

这里:

  • norm(v) - 计算矢量的欧氏常态。

  • norm(v, 1) - 计算一阶的规范(元素的模数之和)。

  • norm(m) - 计算矩阵的欧氏常模(弗罗贝尼斯常模)。

  • norm(m, Inf) - 计算无穷大的规范(最大行和)。示例中 = 4.0

检查
检查

功能名称

说明

示例

isempty.

检查数组、向量或矩阵是否为空。如果对象为空,则返回 true,否则返回 false

# Проверка пустого и непустого 向量а
v1 = []
v2 = [1, 2, 3]
isempty(v1)
isempty(v2)

# Проверка пустой и непустой матрицы
m1 = reshape([], 0, 0)
m2 = [1 2; 3 4]
isempty(m1)
isempty(m2)

# Проверка пустого и непустого массива
a1 = Int[]
a2 = [1, 2, 3, 4]
isempty(a1
isempty(a2)

此处:

  • 对于向量:

    • isempty(v1)返回`true,因为`v1`不包含任何元素。

    • isempty(v2)返回`false,因为向量`v2`包含三个元素`[1, 2, 3]`。

  • 对于矩阵

    • 由于矩阵 m1 的大小为 0×0,因此 isempty(m1) 返回 true

    • 由于矩阵 m2 的大小为 2×2,因此 isempty(m2) 返回`false`。

  • 对于数组

    • 由于数组 a1 为空,所以 isempty(a1) 返回 true

    • isempty(a2) 返回 false ,因为数组 a2 包含四个元素。

iszero.

检查对象是否为空。如果对象为空,则返回 true,否则返回 false

支持数值类型以及数组、矩阵和向量(在 Julia 中,如果对象的所有元素都为零,则该对象为空)。

[源代码,julia].

# Проверка числа
x = 0
y = 5
iszero(x)  # true
iszero(y)  # false

# Проверка 向量а
v1 = [0, 0, 0]
v2 = [0, 1, 0]
iszero(v1)  # true
iszero(v2)  # false

# Проверка матрицы
m1 = zeros(2, 2)нулями
m2 = [1 0; 0 0]элементом
iszero(m1)  # true
iszero(m2)  # false

# Проверка многомерного массива
a1 = zeros(2, 2, 2)
a2 = reshape([1, 0, 0], 1, 3)
iszero(a1)  # true
iszero(a2)  # false

这里

用于数字:

  • iszero(x) 返回`true`,因为`x = 0`。

  • iszero(y) 返回`false`,因为`y = 5`。

对于向量

  • iszero(v1) 返回`true`,因为向量 v1 的所有元素都是 0。

  • iszero(v2) 返回 false ,因为向量 v2 的第二个元素等于 1

对于矩阵

  • 因为矩阵 m1 的所有元素都等于 0,所以 iszero(m1) 返回 true

  • iszero(m2) 返回`false`,因为矩阵 m2 包含一个非零元素 1

对于多维数组:

  • iszero(a1) 返回 true,因为数组 a1 的所有元素都等于 0

  • iszero(a2) 返回`false`,因为数组 a2 的第一个元素等于`1`。

issymmetric.

检查矩阵是否对称。如果矩阵等于其转置副本,则返回 true,否则返回 false。只适用于正方形矩阵;其他格式的矩阵返回 false

[源代码,julia].

# Симметричная 矩阵
m1 = [1 2 3; 2 4 5; 3 5 6]
issymmetric(m1)  # true

# Несимметричная 矩阵
m2 = [1 0 0; 0 4 5; 3 5 6]
issymmetric(m2)  # false

# Квадратная, но несимметричная 矩阵
m3 = [1 2; 3 4]
issymmetric(m3)  # false

# Несимметричная прямоугольная 矩阵
m4 = [1 2; 2 3; 3 4]
issymmetric(m4)  # false

此处:

  • 用于矩阵 m1

    矩阵 m1 等于它的转置副本:

    [1 2 3]       [1 2 3]
    [2 4 5]  ->   [2 4 5]
    [3 5 6]       [3 5 6]

    issymmetric(m1) 返回 true

  • 对于矩阵 m2

    矩阵 m2 不等于它的转置副本:

    [1 0 0]       [1 0 3]
    [0 4 5]  ->   [0 4 5]
    [3 5 6]       [0 5 6]

    issymmetric(m2) 返回`false`。

  • 对于矩阵 m3

    矩阵 m3 是正方形,但不对称:

    [1 2]       [1 3]
    [3 4]  ->   [2 4]

    issymmetric(m3) 返回`false`。

  • 对于矩阵 m4

    矩阵 m4 是矩形(不是正方形),因此 issymmetric(m4) 返回`false`。

变换.
Transformation

函数名称

说明

示例

vec.

将矩阵或多维数组转换为向量。它会返回一个一维数组,其中的元素取自原始矩阵或数组的列。如果参数已经是一个向量,则返回值不变。

[源代码,julia].

# Преобразование матрицы в 向量
m = [1 2; 3 4]
v1 = vec(m)  # [1, 3, 2, 4]

# Преобразование трехмерного массива в 向量
a = zeros(2, 2, 2)
a[:, :, 1] .= [1 2; 3 4]
a[:, :, 2] .= [5 6; 7 8]
v2 = vec(a)  # [1, 3, 2, 4, 5, 7, 6, 8]

# Преобразование 向量а (без изменений)
v = [1, 2, 3]
v3 = vec(v)  # [1, 2, 3]
  • 矩阵 m 的形式为

    2×2 Matrix{Int64}:
     1  2
     3  4

    函数 vec 从每列中依次提取元素,将其转换为矢量:

    [1, 3, 2, 4]
  • 对于三维数组 a

    原始数组`a`看起来是这样的(按层数):

    #Слой 1
    [1 2]
    [3 4]
    
    #Слой 2
    [5 6]
    [7 8]

    vec 将其转换为矢量:

    [1, 3, 2, 4, 5, 7, 6, 8]

    对于向量 v

    如果对象已经是一个向量,`vec`会原封不动地返回:

    3-element Vector{Int64}:
     1
     2
     3

permutedims.

重新排列多维数组的测量值(轴)。 可以在不改变数据本身的情况下改变测量的顺序,创建一个具有重新排列的轴的新数组。

A = reshape(collect(1:6), 2, 3)  # 2×3 массив
B = permutedims(A, (2, 1))  # Меняем местами оси 1 и 2

这里:

  • permutedims(A, (2, 1)) - 交换行和列,即转置矩阵。

  • 该函数在不改变 A 的情况下创建一个新数组(与 transpose 不同,后者只适用于二维矩阵)。

  • 您可以对任意维数进行转置,例如,`permutedims(A, (2, 1, 3))`适用于三维数组。

hcat / vcat.

数组的横向和纵向连接(并集)。

  • hcat(水平连接)- 水平(按列)连接数组或矢量,形成新的矩阵或数组。

  • vcat`(垂直连接)- 垂直(跨行)合并数组或矢量,形成新的矩阵或数组。

[源代码,julia].

# Горизонтальное объединение (hcat)
v1 = [1, 2, 3]
v2 = [4, 5, 6]
h_result = hcat(v1, v2)

# Вертикальное объединение (vcat)
v3 = [7, 8, 9]
v_result = vcat(v1, v3)

# Объединение матриц
m1 = [1 2; 3 4]
m2 = [5 6; 7 8]
hcat_result = hcat(m1, m2)
vcat_result = vcat(m1, m2)

这里:

  • h_result = hcat(v1, v2)` 水平连接成一个 3x2 矩阵:

    3×2 Matrix{Int64}:
     1  4
     2  5
     3  6
  • v_result = vcat(v1, v3) 合并成一个向量:

    6-element Vector{Int64}:
     1
     2
     3
     7
     8
     9
  • hcat_result = hcat(m1, m2) 合并成一个 2x4 矩阵:

    2×4 Matrix{Int64}:
     1  2  5  6
     3  4  7  8
  • vcat_result = vcat(m1, m2)` 合并成一个 4x2 矩阵:

    4×2 Matrix{Int64}:
     1  2
     3  4
     5  6
     7  8

复制

创建数组、向量或矩阵的独立副本。对副本所做的更改不会影响原始对象,反之亦然。

[源代码,朱莉娅].

v = [1, 2, 3]
v_copy = copy(v)
v[1] = 10  # Изменяем оригинал
println(v)       # [10, 2, 3]
println(v_copy)  # [1, 2, 3]

这里

  • 改变原始对象中的元素(v[1] = 10)不会影响副本`v_copy`。

deepcopy.

创建数组的深度副本,递归复制所有嵌套结构。对副本的修改不会影响原数组。在 Julia 中,默认赋值传递的是对象引用而不是值。如果需要创建一个独立的副本,有两种方法:

  • copy`--创建一个浅层拷贝(新的容器,但引用相同的项目)。

  • deepcopy - 深度复制(递归复制所有内容)。

[源代码,朱莉娅].

A = [[1, 2], [3, 4]]
B = copy(A)       # Неглубокая копия
C = deepcopy(A)   # Глубокая копия

B[1][1] = 99
println(A)  # [[99, 2], [3, 4]]  — A изменился, потому что B и A связаны
println(C)  # [[1, 2], [3, 4]]  — Глубокая копия не изменилась

这里:

  • 改变原始文件中的嵌套元素(v[1][1] = 10)不会影响`v_deepcopy`的深度拷贝。

广播

允许对数组元素进行自动大小匹配(广播)操作。详情请参见此处

[源代码,julia]。

# Пример с 向量ом
v = [1, 2, 3]
v_squared = broadcast(x -> x^2, v)

# Пример с матрицей
m = [1 2; 3 4]
m_doubled = broadcast(x -> x * 2, m)

# Пример с разными размерами массивов
a = [1, 2, 3]
b = [4, 5]
result = broadcast(+, a, b')

此处:

  • v_squared = broadcast(x -> x^2, v) 形式:

    3-element Vector{Int64}:
     1
     4
     9
  • m_doubled = broadcast(x -> x * 2, m) 表格:

    2×2 Matrix{Int64}:
     2  4
     6  8
  • result = broadcast(+, a, b') 表格:

    3×2 Matrix{Int64}:
     5  6
     6  7
     7  8

    b'` 是一个转置向量。

  • broadcast(x -> x^2, v)` - 向量元素的平方

使用数组的适当性

数组是一种方便灵活的数据处理工具,但 Julia 的其他结构可能更适合某些任务。详见下文。

何时推荐使用数组

  • 通过索引快速访问元素 - 数组在内存中按顺序存储元素,允许通过索引即时访问任何元素。例如,ar[3] 将立即返回数组的第三个元素。这被称为 随机存取(随机存取),运行时间为 O(1)(无论输入数据的大小如何,操作所需的时间不变,即无论数组有多大,按索引访问元素所需的时间相同)。

  • 在末尾高效添加和删除 - 如果需要经常在数组末尾添加或删除元素,那么可以使用`push!(添加一个元素)和`pop!(删除最后一个元素)函数。这些操作速度非常快,因为它们不需要重新排列其他元素。

  • 处理固定数量的数据 - 如果事先知道要存储多少个元素,数组的工作效率会特别高。数组可以一次性分配内存,从而将调整大小的开销降至最低。

  • 矢量计算和线性代数 - Julia 优化了数组,尤其是数值数组的处理。如果要处理矩阵、向量或执行线性代数运算,数组是最佳选择。例如,处理矩阵的函数(如 dotcross)或通过broadcast 进行的数组运算(.+.*)在数组中运行速度更快。

不推荐使用数组时

  • 频繁添加或删除中间或开头的元素 - 如果需要频繁插入或删除数组开头或中间的元素。例如,"insert!"(插入)和 "deleteat!"(删除)函数需要移动所有后续元素,因此对于大型数组来说效率很低。替代方法:使用 DataStructures.jl 包中的 Deque 函数,它对两端的插入和删除进行了优化。

  • 按键查找项目 - 如果需要按唯一键(如用户名或 ID)快速查找项目,则不适合使用数组,因为数组是通过搜索所有项目来查找的(这相当耗时)。替代方法:使用 Dict(字典),它可以让你按键快速查找项目。

  • 频繁调整结构大小--如果数据结构频繁变化(例如,在任意位置添加或删除元素),数组就会失效。替代方法:考虑使用link:https://juliacollections.github.io/DataStructures.jl/latest/ 包 [DataStructures.jl] 中的 SetDict 或列表结构(如 List)。

  • 使用不可变数据 - Julia 中的数组是可变的,这意味着它们的元素在创建后可以更改。如果需要不可变的数据结构,最好使用元组(Tuple)。元组不允许更改元素,因此便于存储恒定数据。例如

    t = (1, 2, 3)
    t[1] = 10  # Ошибка! Кортежи неизменяемы

字符串和符号的数组、矩阵和向量

在 Julia 中,数组、矩阵和向量可以像数字一样包含字符串或符号。

# Вектор строк
v = ["apple", "banana", "cherry"]
println(v[1])  # apple

# Матрица символов
m = ['a' 'b'; 'c' 'd']
println(m[1, 2])  # b

# Трехмерный массив строк
a = [["a", "b"], ["c", "d"]]
println(a[1][2])  # "b"
  • 字符串向量—​每个字符串都作为一维数组的一个元素存储。

  • 字符矩阵 - 一个二维数组,每个元素都是一个字符。

  • 字符串三维数组 - 支持文本数据的任意维数。

Julia 中的数组默认为动态数组,但其长度是固定的,除非明确更改。这意味着创建数组时,其当前长度保持不变,直到使用了 "push!"、"append!"或 "resize!"等特殊方法。这样做是为了提高性能:固定长度的操作不需要不断重新分配内存,因此速度更快。

带有 end 的更复杂的结构(如 end+1)不允许直接为数组元素赋值,因为此类操作超出了当前长度。要添加新元素,必须明确地增加数组的大小。例如,可以使用 resize!

a = [10, 20, 30]
resize!(a, length(a) + 1)  # Расширяем массив на 1 элемент
a[end] = 40  # Присваиваем значение новому элементу
println(a)  # [10, 20, 30, 40]

带有 end 的构造可用于对现有数组边界内的索引进行索引和算术运算。例如

  • a[end] - 访问最后一个元素。

  • a[end-1] - 访问从末尾开始的第二个元素。

  • a[1:end] - 访问整个数组。

  • a[1:end-1] - 获取除最后一个元素以外的所有元素。

在 Julia 中,不能直接为索引为 end+1 的元素赋值,也不能为超出数组当前长度的任何索引赋值。要调整数组的大小,必须使用特殊的方法,如`resize!、`push!`或`append!

数组索引

Julia 中的索引从 1 开始,即数组的第一个元素的索引为 1。数组还支持特殊的 "end "索引,表示数组的最后一个元素或相应维度的大小。索引示例

a = [10, 20, 30, 40]
println(a[1])  # 10 — первый элемент
println(a[end])  # 40 — последний элемент

# Индексация матриц
m = [1 2; 3 4]
println(m[1, end])  # 2 — последний элемент первой строки
  • 索引 1 总是指向第一个元素。

  • end "用于指一维和多维数组中的最后一个元素。

  • 对于矩阵,第一个索引是行号,第二个索引是列号。

*其他索引变化:

  • 使用范围可以同时引用数组中的多个元素:

    b = [1, 2, 3, 4, 5]
    println(b[2:end])  # [2, 3, 4, 5] — элементы со второго до последнего
  • 以特定增量选择元素:

    b = [1, 2, 3, 4, 5]
    println(b[1:2:end])  # [1, 3, 5] — элементы с шагом 2

    在 Julia 中,"1:2:end "形式的表达式称为范围。范围是一种结构,它描述了一个有起点、级数和终点的数字序列。例如,1:2:5`创建了一个以 2 为增量从 1 到 5 的序列:[1, 3, 5]`。

    在这个例子中,1:2:end 表示选择从数组的第一个元素(1)开始,以增量`2`进行,并以数组的最后一个元素(end)结束。使用范围可以方便有效地处理数组和矩阵索引。使用范围的示例

    # Простые диапазоны
    r1 = 1:5           # Создает последовательность [1, 2, 3, 4, 5]
    r2 = 1:2:10        # Создает последовательность [1, 3, 5, 7, 9]
    
    # Использование диапазона для индексации
    a = [10, 20, 30, 40, 50]
    println(a[2:4])    # [20, 30, 40]
    println(a[1:2:end]) # [10, 30, 50]
    
    # Диапазон с "end"
    println(a[3:end])  # [30, 40, 50]
  • 选择符合特定条件的项目(详见章节)。 逻辑索引):

    b = [1, 2, 3, 4, 5]
    println(b[b .> 3])  # [4, 5] — элементы больше 3

在 Julia 中,不仅可以直接设置范围,还可以使用变量来设置范围。例如

arr = [10, 20, 30, 40, 50]
a = 1:2:5         # Задаем диапазон в переменной
println(arr[a])   # [10, 30, 50]

逻辑索引

Julia 中的逻辑索引允许您根据返回与原始数组维度相同的逻辑数组(true/false)的条件来选择数组元素。这种方法对于过滤数据非常有用。

+ 示例

# Исходный массив
a = [10, 20, 30, 40, 50]

# Условие: выбрать элементы больше 25
filtered = a[a .> 25]  # [30, 40, 50]
println(filtered)

# Условие: элементы, которые кратны 10
filtered = a[a .% 10 .== 0]  # [10, 20, 30, 40, 50]
println(filtered)

这里

  • 条件前的 . 运算符(.>, .==)表示分段运算。关于此类运算的更详细说明,请参阅矢量化和逻辑索引 一文。

  • 逻辑数组 `[false,false,true,true,true]`将用于选择相应的元素。

多维数组示例:

# Матрица 2x3
m = [1 2 3; 4 5 6]

# Условие: выбрать элементы больше 3
filtered = m[m .> 3]  # [4, 5, 6]
println(filtered)

处理数组、向量和矩阵的操作符

Julia 提供的操作符可以简化数组的处理,无论是一维数组(矢量)、二维数组(矩阵)还是更复杂的多维数组结构。以下是用于索引、转换和组合数据的主要操作符:

  • 操作符 : 用于沿特定维度选择数组的所有元素或创建范围。

    例如

    # Исходный массив
    m = [1 2 3; 4 5 6; 7 8 9]
    
    # Все элементы первой строки
    println(m[1, :])  # [1, 2, 3]
    
    # Все элементы второго столбца
    println(m[:, 2])  # [2, 5, 8]
    
    # Диапазон индексов
    println(m[1:2, 1:2])  # [1 2; 4 5]
  • ''''运算符用于连接 (实数的转置)。它只适用于数字数组。

    例如

    # Вектор-строка
    v = [1 2 3]
    
    # Транспонирование в столбец
    println(v')  # [1; 2; 3;;]
    要使用复数对数组进行换置,' 运算符也会返回复数共轭结果。如果只需要行到列的转置(不需要共轭),请使用 transpose 函数。

要对包含非数字元素(如字符串或用户定义类型)的数组进行换置,请使用 permutedims 函数。与针对数值数据的 transpose 不同,permutedims 适用于任何类型的数据。

如果将 ' 运算符用于非数值数组,会导致错误。在 Julia 中,`` 运算符调用`adjoint`(共轭转置),该运算符用于数值和复杂数组。对于字符串和其他对象,它没有定义,因此会导致 "方法错误"。例如

arr = ["a" "b"; "c" "d"] # Матрица строк (2×2)
arr_transposed = permutedims(arr, (2, 1)) # Меняем строки и столбцы местами
arr_wrong = arr' # Ошибка!
  • 操作符 ; 用于纵向组合数组,即添加行。

    例如

    # Исходные 向量ы
    a = [1, 2, 3]
    b = [4, 5, 6]
    
    # Вертикальная конкатенация
    result = [a; b]
    println(result)  # 6-element Vector{Int64}:[1; 2; 3; 4; 5; 6]

使用 for 对数组进行遍历

在 Julia 中,使用 for 循环可以方便地遍历数组。让我们来看看通过 for 处理数组的基本方法。以下语法用于循环遍历数组中的所有元素:

arr = [10, 20, 30, 40]

for x in arr
    println(x)
end
输出
10
20
30
40

有时不仅需要获取值,还需要获取它们的索引。为此,可以使用 eachindex 自动选择最佳索引方法:

arr = ["a", "b", "c"]

for i in eachindex(arr)
    println("Элемент ", i, ": ", arr[i])
end
输出
Элемент 1: a
Элемент 2: b
Элемент 3: c

另一种获取索引和值的方法是使用`enumerate`函数:

arr = ["apple", "banana", "cherry"]

for (i, val) in enumerate(arr)
    println("$i: $val")
end
输出
1: apple
2: banana
3: cherry

对于多维数组,可以使用嵌套循环:

matrix = [1 2 3; 4 5 6]

for i in 1:size(matrix, 1)  # Проход по строкам
    for j in 1:size(matrix, 2)  # Проход по столбцам
        println("matrix[$i, $j] = ", matrix[i, j])
    end
end
输出
matrix[1, 1] = 1
matrix[1, 2] = 2
matrix[1, 3] = 3
matrix[2, 1] = 4
matrix[2, 2] = 5
matrix[2, 3] = 6

您可以直接使用 for 代替嵌套循环:

matrix = [1 2 3; 4 5 6]

for x in matrix
    println(x)
end
输出
1
4
2
5
3
6

Julia 按列而不是按行遍历元素。要按行绕过数组,可以使用`permutedims`或`eachrow`:

for row in eachrow(matrix)
    println(row)
end
输出
[1, 2, 3]
[4, 5, 6]