==
和 ===
在 Julia 中的比较运算符有什么区别?
===
检查对象标识:如果 x
和 y
是相同的对象,存储在内存中的相同位置,则 x === y
为真。x
和 y
具有相同的类型 - 因此具有相同的结构 - 并且它们的对应组件都是递归的 ===
,则 x === y
为真。Int
或 Float64
这样的不可变数据块),如果 x
和 y
包含完全相同的位,则 x === y
为真。这些规则递归应用,定义了 ===
的行为。
另一方面,==
函数是用户可定义的,并实现 "抽象值相等性"。重载性是一个关键区别:
===
不能被重载 - 它是一个内置函数,具有固定的预定义行为。您不能扩展或更改它的行为。==
可以被重载 - 它是一个普通(对于Julia来说)具有中缀语法的通用函数。它有回退定义,为用户定义的类型提供有用的默认行为,但您可以通过为您的类型添加新的、更具体的方法到 ==
中来自定义其行为。关于如何为内置类型和用户定义类型扩展 ==
的行为,以及它在这些类型上的行为,可以参考 文档:
例如,所有数值类型都按数值比较,忽略类型。字符串则按字符序列比较,忽略编码。
您可以将其视为 "直观相等"。如果两个数字在数值上相等,则它们是 ==
的:
julia> 1 == 1.0 == 1 + 0im == 1.0 + 0.0im == 1//1
true
julia> 0.5 == 1/2 == 1//2
true
==
实现的是精确的数值相等性:julia> 2/3 == 2//3
false
2/3
是浮点数值 0.6666666666666666
,它是最接近数学值 2/3(或者在 Julia 中有理数表示法为 2//3
)的 Float64
,但 0.6666666666666666
不完全等于 2/3。此外,==
遵循浮点数 IEEE 754 语义。0.0
和 -0.0
):它们是 ==
的,即使它们的行为不同,因此不是 ===
。
- 存在许多不同的非数字 (NaN
) 值:它们不等于自己、彼此或任何其他值;它们每个都是 ===
自己,但不是 !==
彼此,因为它们具有不同的位。julia> 0.0 === -0.0
false
julia> 0.0 == -0.0
true
julia> 1/0.0
Inf
julia> 1/-0.0
-Inf
julia> NaN === NaN
true
julia> NaN === -NaN
false
julia> -NaN === -NaN
true
julia> NaN == NaN
false
julia> NaN == -NaN
false
julia> NaN == 1.0
false
这有点令人困惑,但这是IEEE标准。
此外,==
的文档也指出:
集合通常应通过对所有内容递归调用
==
来实现==
。
因此, ==
给出的值相等概念在集合中被递归地扩展:
julia> [1, 2, 3] == [1, 2, 3]
true
julia> [1, 2, 3] == [1.0, 2.0, 3.0]
true
julia> [1, 2, 3] == Any[1//1, 2.0, 3 + 0im]
true
==
比较的缺点:julia> a = [1, NaN, 3]
3-element Array{Float64,1}:
1.0
NaN
3.0
julia> a == a
false
===
比较始终测试对象标识,因此即使两个数组具有相同的类型并包含相同的值,只有它们是同一个数组时才相等:julia> b = copy(a)
3-element Array{Float64,1}:
1.0
NaN
3.0
julia> a === a
true
julia> a === b
false
julia> b === b
true
a
和b
不是===
的原因是,尽管它们在此处当前包含相同的数据,但由于它们是可变的且不是同一对象,您可以更改其中一个,然后它将变得不同:
julia> a[1] = -1
-1
julia> a # different than before
3-element Array{Int64,1}:
-1
2
3
julia> b # still the same as before
3-element Array{Int64,1}:
1
2
3
a
和b
是不同的对象。然而,相同的逻辑并不适用于不可变对象:如果它们包含相同的数据,则只要它们具有相同的值,它们就无法区分。因此,不可变值被释放出与特定位置绑定的束缚,这是编译器能够如此有效地优化使用不可变值的原因之一。===
表示它们实际上是同一个对象,即变量指向内存中的同一位置。 ==
表示对象具有相同的值。例如:
julia> A = rand(5,5) #Make an array
5x5 Array{Float64,2}:
0.349193 0.408216 0.703084 0.163128 0.815687
0.211441 0.0185634 0.378299 0.0734293 0.187445
0.667637 0.139323 0.286794 0.359962 0.229784
0.476224 0.49812 0.648244 0.831006 0.1787
0.960756 0.488886 0.195973 0.148958 0.200619
julia> B = A # This sets the pointer of B to the pointer of A
5x5 Array{Float64,2}:
0.349193 0.408216 0.703084 0.163128 0.815687
0.211441 0.0185634 0.378299 0.0734293 0.187445
0.667637 0.139323 0.286794 0.359962 0.229784
0.476224 0.49812 0.648244 0.831006 0.1787
0.960756 0.488886 0.195973 0.148958 0.200619
julia> B === A # Same spot in memory
true
julia> B[1,1]=2 #Change a value of B
2
julia> B
5x5 Array{Float64,2}:
2.0 0.408216 0.703084 0.163128 0.815687
0.211441 0.0185634 0.378299 0.0734293 0.187445
0.667637 0.139323 0.286794 0.359962 0.229784
0.476224 0.49812 0.648244 0.831006 0.1787
0.960756 0.488886 0.195973 0.148958 0.200619
julia> A #Also changes A since they point to the same spot
5x5 Array{Float64,2}:
2.0 0.408216 0.703084 0.163128 0.815687
0.211441 0.0185634 0.378299 0.0734293 0.187445
0.667637 0.139323 0.286794 0.359962 0.229784
0.476224 0.49812 0.648244 0.831006 0.1787
0.960756 0.488886 0.195973 0.148958 0.200619
julia> B = copy(A) #Now make B a copy of A, no longer the same pointer
5x5 Array{Float64,2}:
2.0 0.408216 0.703084 0.163128 0.815687
0.211441 0.0185634 0.378299 0.0734293 0.187445
0.667637 0.139323 0.286794 0.359962 0.229784
0.476224 0.49812 0.648244 0.831006 0.1787
0.960756 0.488886 0.195973 0.148958 0.200619
julia> B === A # Now this is false
false
julia> B == A # This is still true
true
julia> B[1,1] = 1 #Changing B
1
julia> B
5x5 Array{Float64,2}:
1.0 0.408216 0.703084 0.163128 0.815687
0.211441 0.0185634 0.378299 0.0734293 0.187445
0.667637 0.139323 0.286794 0.359962 0.229784
0.476224 0.49812 0.648244 0.831006 0.1787
0.960756 0.488886 0.195973 0.148958 0.200619
julia> A #Now does not change A
5x5 Array{Float64,2}:
2.0 0.408216 0.703084 0.163128 0.815687
0.211441 0.0185634 0.378299 0.0734293 0.187445
0.667637 0.139323 0.286794 0.359962 0.229784
0.476224 0.49812 0.648244 0.831006 0.1787
0.960756 0.488886 0.195973 0.148958 0.200619
==
可以被重载,而===
不行。2)===
比较不可变对象的内容。其思想是只有当无法区分x
和y
时,x === y
才为真。这也被称为等值谓词。 - Toivo Henningsson