朱莉娅的“==”和“===”比较运算符有什么区别?

时间:2016-07-26 22:52:57

标签: julia

Julia中的=====比较运算符之间有什么区别?

2 个答案:

答案 0 :(得分:13)

@ ChrisRackauckas的回答是准确的 - 即对于可变对象。然而,问题还有一些问题,所以我会在这里详细说明一下。

===运算符(is函数的别名)实现了Henry Baker的EGAL谓词[12]:x === y在两个时为真对象在编程上无法区分 - 即您无法编写代表xy之间任何差异的代码。这归结为以下规则:

  • 对于可变值(数组,可变复合类型),===检查对象标识:如果x === yx是同一个对象,则y为真,存储在记忆中的相同位置。
  • 对于不可变复合类型,如果x === yx具有相同的类型(因此结构相同),则y为真,并且它们的相应组件都是递归===
  • 对于位类型(不可变的数据块,如IntFloat64),如果x === yx包含完全相同的位,则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

ab不是===的原因是即使他们当前碰巧在这里包含相同的数据,因为它们是可变的并且不是同一个对象,你可以改变其中一个,然后很明显它们是不同的:

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

因此,您可以通过变异判断ab是不同的对象。相同的逻辑不适用于不可变对象:如果它们包含相同的数据,只要它们具有相同的值,它们就无法区分。因此,不可变值从绑定到特定位置中解放出来,这是编译器能够如此有效地优化不可变值的使用的原因之一。

另见:

答案 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