“与”的区别是什么==&引用;及===&引用;Julia中的比较运算符?

“与”的区别是什么==&引用;及===&引用;Julia中的比较运算符?,julia,Julia,Julia中的比较运算符与==之间有什么区别?==意味着它实际上是同一个对象,即变量指向内存中的同一点=表示对象具有相同的值。例如: 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.13932

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

==
意味着它实际上是同一个对象,即变量指向内存中的同一点<代码>=表示对象具有相同的值。例如:

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

@Chrisrackaukas的答案就其本身而言是准确的——即对于可变对象。然而,问题还不止于此,所以我将在这里详细阐述一下

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

  • 对于可变值(数组、可变复合类型),
    ==
    检查对象标识:
    x===y
    如果
    x
    y
    是存储在内存中相同位置的相同对象,则为true
  • 对于不可变的复合类型,
    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.666666
,它是最接近数学值2/3的
Float64
(或者在有理值的Julia表示法中,
2//3
),但
0.666666
并不完全等于2/3。而且,
==

浮点数遵循IEEE 754语义

这包括一些可能意外的属性:

  • 有不同的正浮点零和负浮点零(
    0.0
    -0.0
    ):它们是
    =
    ,尽管它们的行为不同,因此不是
    =
  • 有许多不同的not-a-number(
    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
是不同的对象。同样的逻辑不适用于不可变对象:如果它们包含相同的数据,则只要它们具有相同的值,就无法区分。因此,不可变值从绑定到特定位置的数据中解放出来,这也是编译器能够如此有效地优化不可变值使用的原因之一

另请参见:


Hm.也许可以在Julia网站上搜索Julia lang的文档-在谷歌开始搜索的30秒内,我就可以访问这些文档并搜索===了。冷静点。有些人不理解文档的一部分是可以的,并且需要以其他方式进行说明。我们都去过那儿。@chrisrackaukas我刚接到楼上的电话。你的pitchfork权限已被撤销。在文档中搜索你不知道名称的内容很棘手。在Julia docs上,搜索可以找到
Base==但搜索结果为零。如果我猜
==
将在基本函数中,我是对的,但我只看到它在操作顺序中的位置。最后,通过谷歌搜索“三重相等”,我发现了这个问题(这是很好的答案!