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

Waj*_*jih 12 julia

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

Ste*_*ski 17

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

===运营商(为一个别名is功能)实现了亨利·贝克的EGAL谓词[ 1,2 ]:x === y当两个对象编程的区分是真实的-即你可以不写,演示什么区别代码xy.这归结为以下规则:

  • 对于可变值(数组,可变复合类型),===检查对象标识:x === y如果xy是同一对象,则为true ,存储在内存中的相同位置.
  • 对于不可变复合类型,x === y如果xy具有相同的类型(因此具有相同的结构),则它们是真的,并且它们的相应组件都是递归的===.
  • 对于比特类型(如数据的不可变的组块IntFloat64),x === y是如果为真x,并y恰好包含相同的比特.

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

==另一方面,该函数是用户可定义的,并实现"抽象值相等".可过载性是一个关键的区别:

  • ===是不重载-它是与固定的,预定义的行为内置函数.您无法扩展或更改其行为.
  • ==是重载-这是与缀语法正常(朱莉亚)泛型函数.它具有后备定义,可以为用户定义的类型提供有用的默认行为,但您可以通过==为类型添加新的,更具体的方法来更改它.

要提供有关==内置类型的行为以及人们在扩展它时应如何对用户定义类型执行操作的更多详细信息,请参阅以下文档:

例如,所有数字类型都通过数值进行比较,忽略类型.将字符串作为字符序列进行比较,忽略编码.

您可以将其视为"直觉平等".如果两个数字在数值上相等,它们是==:

julia> 1 == 1.0 == 1 + 0im == 1.0 + 0.0im == 1//1
true

julia> 0.5 == 1/2 == 1//2
true
Run Code Online (Sandbox Code Playgroud)

但请注意,它==实现了精确的数字相等:

julia> 2/3 == 2//3
false
Run Code Online (Sandbox Code Playgroud)

这些值是不相等的,因为2/3它是浮点值0.6666666666666666,它最接近Float64数学值2/3(或合理值的Julia表示法2//3),但0.6666666666666666不完全等于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
Run Code Online (Sandbox Code Playgroud)

这有点令人困惑,但这是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
Run Code Online (Sandbox Code Playgroud)

因此,这继承了标量==比较的缺点:

julia> a = [1, NaN, 3]
3-element Array{Float64,1}:
   1.0
 NaN
   3.0

julia> a == a
false
Run Code Online (Sandbox Code Playgroud)

===另一方面,比较总是测试对象标识,因此即使两个数组具有相同的类型并包含相同的值,如果它们是相同的数组,它们也是相等的:

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
Run Code Online (Sandbox Code Playgroud)

究其原因是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
Run Code Online (Sandbox Code Playgroud)

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

也可以看看:


Chr*_*kas 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
Run Code Online (Sandbox Code Playgroud)

  • 另外:1)`==`是可重载的,而`===`则不是.2)`===`比较`immutable`对象的内容.我们的想法是,只有在无法区分`x`和`y`时,`x === y`应该是真的.这也被称为egal谓词. (4认同)