使用和等于
有三个相等运算符:==,=== 和 isequal。 (最后一个不是真正的运算符,但它是一个函数,所有运算符都是函数。)
什么时候使用 ==
== 是价值相等。当两个对象在其当前状态下表示相同的值时,它返回 true。
例如,很明显
julia> 1 == 1
true
但此外
julia> 1 == 1.0
true
julia> 1 == 1.0 + 0.0im
true
julia> 1 == 1//1
true
上面每个相等的右边是不同的类型 ,但它们仍然代表相同的值。
对于可变对象,如数组 ,== 比较它们的现值。
julia> A = [1, 2, 3]
3-element Array{Int64,1}:
1
2
3
julia> B = [1, 2, 3]
3-element Array{Int64,1}:
1
2
3
julia> C = [1, 3, 2]
3-element Array{Int64,1}:
1
3
2
julia> A == B
true
julia> A == C
false
julia> A[2], A[3] = A[3], A[2] # swap 2nd and 3rd elements of A
(3,2)
julia> A
3-element Array{Int64,1}:
1
3
2
julia> A == B
false
julia> A == C
true
大多数时候,== 是正确的选择。
什么时候使用 ===
=== 比 == 更严格的操作。它不是价值相等,而是衡量价值。如果两个对象无法通过程序本身彼此区分,则它们是相等的。因此我们有
julia> 1 === 1
true
因为没有办法告诉 1 除了另一个 1。但
julia> 1 === 1.0
false
因为尽管 1 和 1.0 是相同的值,但它们的类型不同,因此程序可以区分它们。
此外,
julia> A = [1, 2, 3]
3-element Array{Int64,1}:
1
2
3
julia> B = [1, 2, 3]
3-element Array{Int64,1}:
1
2
3
julia> A === B
false
julia> A === A
true
这可能起初看起来令人惊讶! 该程序如何区分两个向量 A 和 B?因为向量是可变的,它可以修改 A,然后它的行为与 B 不同。但无论它如何修改 A,A 将始终与 A 本身相同。因此,A 对于 A 来说是天生的,但对于 B 来说并不是真的。
继续沿着这个脉络,观察
julia> C = A
3-element Array{Int64,1}:
1
2
3
julia> A === C
true
通过将 A 分配给 C,我们说 C 已经别名 A。也就是说,它已成为 A 的另一个名称。对 A 所做的任何修改也将由 C 观察到。因此,没有办法区分 A 和 C 之间的区别,因此它们是相等的。
什么时候使用 isequal
== 和 isequal 之间的区别非常微妙。最大的区别在于如何处理浮点数:
julia> NaN == NaN
false
这可能令人惊奇的结果是限定由用于浮点类型(IEEE-754)的 IEEE 标准。但是在某些情况下这没有用,例如排序。isequal 是为这些情况提供的:
julia> isequal(NaN, NaN)
true
在光谱的另一面,== 将 IEEE 负零和正零视为相同的值(也是 IEEE-754 规定的)。然而,这些值在存储器中具有不同的表示。
julia> 0.0
0.0
julia> -0.0
-0.0
julia> 0.0 == -0.0
true
再次出于分类目的,isequal 区分它们。
julia> isequal(0.0, -0.0)
false