Julia中的==
和===
比较运算符之间有什么区别?
答案 0 :(得分:13)
@ ChrisRackauckas的回答是准确的 - 即对于可变对象。然而,问题还有一些问题,所以我会在这里详细说明一下。
===
运算符(is
函数的别名)实现了Henry Baker的EGAL谓词[1,2]:x === y
在两个时为真对象在编程上无法区分 - 即您无法编写代表x
和y
之间任何差异的代码。这归结为以下规则:
===
检查对象标识:如果x === y
和x
是同一个对象,则y
为真,存储在记忆中的相同位置。x === y
和x
具有相同的类型(因此结构相同),则y
为真,并且它们的相应组件都是递归===
Int
或Float64
),如果x === y
和x
包含完全相同的位,则y
为真。 这些递归应用的规则定义了===
的行为。
另一方面,==
函数是用户可定义的,并实现“抽象值相等”。可过载性是一个关键的区别:
===
不可重载 - 它是一个内置函数,具有固定的预定义行为。您无法扩展或更改其行为。==
是可重载的 - 它是具有中缀语法的普通(对于Julia)泛型函数。它具有后备定义,可以为用户定义的类型提供有用的默认行为,但您可以根据需要通过向类型==
添加新的,更具体的方法来更改它。提供有关内置类型==
行为的更多详细信息,以及当人们对其进行扩展时应如何对用户定义的类型执行操作,来自the docs:
例如,所有数字类型都按数值进行比较,忽略 类型。将字符串作为字符序列进行比较,忽略 编码
您可以将此视为“直觉平等”。如果两个数字在数值上相等,则为==
:
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最接近的Float64
(或者在理性值的Julia表示法中) ,2//3
),但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
是不同的对象。相同的逻辑不适用于不可变对象:如果它们包含相同的数据,只要它们具有相同的值,它们就无法区分。因此,不可变值从绑定到特定位置中解放出来,这是编译器能够如此有效地优化不可变值的使用的原因之一。
另见:
答案 1 :(得分:11)
===
表示它实际上是同一个对象,即变量指向内存中的相同位置。 ==
表示对象具有相同的值。例如:
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