2016-07-26 86 views
2

Julia的=====比较运算符有什么区别?Julia中的“==”和“===”比较运算符有什么区别?

+0

嗯。也许可以在Julia网站上搜索Julia lang文档 - 我可以在大约30多年的时间内在Google上搜索文档并搜索===。 –

+0

http://docs.julialang.org/en/release-0.4/stdlib/base/#all-objects –

+0

也许如果你澄清你没有关注的文档,这将有所帮助。 –

回答

7

===意味着它实际上是相同的对象,即,变量指向相同的点在存储器中。 ==表示对象具有相同的值。例如:

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 
+4

另外:1)'=='可以重载,而'==='不可以。 2)'==='比较不可变对象的内容。这个想法是,只有当无法区分'x'和'y'时'x === y'应该是真的。这也被称为例证谓词。 –

6

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

===操作者(用于is函数的别名)实现亨利贝克的EGAL谓词[12]:当两个对象编程难以区别x === y为真 - 即不能写入演示xy之间的任何差异的代码。这归结为如下规则:

  • 对于可变值(数组,可变复合类型),===检查对象标识:x === y为真,如果xy是同一个对象,存储在存储器中的相同位置。
  • 对于不可变复合类型,如果xy具有相同类型(因此具有相同的结构)及其相应的组件都是递归的,则x === y为真===
  • 对于位类型(数据的不可变块(如IntFloat64)),如果xy包含完全相同的位,则x === y为真。

这些递归应用的规则定义了===的行为。

==功能,在另一方面,是用户可定义的,并实现“抽象值相等”。过载能力是一个关键的区别:

  • ===不可重载 - 它是一个具有固定的,预先定义的行为的内置函数。你不能扩展或改变它的行为。
  • ==是重载的 - 它是与缀语法正常(朱莉亚)泛型函数。它具有回退定义,它为用户定义的类型提供了有用的默认行为,但您可以根据您的类型在==中添加新的更具体的方法,从而更改它。

为提供有关如何==行为进行更详细的内置类型,它应该如何表现为用户定义类型,当人们进行扩展,从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 

===比较,另一方面总是测试对象的身份,所以即使两个数组具有相同的类型并且包含相同的值,它们也是相等的,如果t哎是相同的阵列:

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是通过突变不同的对象。相同的逻辑不适用于不可变的对象:如果它们包含相同的数据,只要它们具有相同的值,它们就不可区分。因此,不可变值从被绑定到特定位置释放,这是编译器能够如此有效地优化不可变值使用的原因之一。

另请参见:

相关问题