“=="和“=="有什么区别?和“==="Julia中的比较运算符? [英] What is the difference between "==" and "===" comparison operators in Julia?

查看:19
本文介绍了“=="和“=="有什么区别?和“==="Julia中的比较运算符?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

What is the difference between == and === comparison operators in Julia?

推荐答案

@ChrisRackauckas 的回答是准确的——即对于可变对象.不过,这个问题还有很多,所以我会在这里详细说明一下.

@ChrisRackauckas's answer is accurate as far as it goes – i.e. for mutable objects. There's a bit more to the issue than that, however, so I'll elaborate a bit here.

=== 运算符(is 函数的别名)实现 Henry Baker 的 EGAL 谓词 [1, 2]: x === y 当两个对象在编程上无法区分时为真——即你不能编写代码来演示 xy.这归结为以下规则:

The === operator (an alias for the is function) implements Henry Baker's EGAL predicate [1, 2]: x === y is true when two objects are programmatically indistinguishable – i.e. you cannot write code that demonstrates any difference between x and y. This boils down to the following rules:

  • 对于可变值(数组、可变复合类型),=== 检查对象身份:x === y 如果 x 为真> 和 y 是同一个对象,存储在内存中的同一个位置.
  • 对于不可变的复合类型,如果 xy 具有相同的类型,则 x === y 为真 - 因此具有相同的结构– 及其对应的组件都是递归的===.
  • 对于位类型(不可变的数据块,如 IntFloat64),如果 x,则 x === y 为真y 包含完全相同的位.
  • For mutable values (arrays, mutable composite types), === checks object identity: x === y is true if x and y are the same object, stored at the same location in memory.
  • For immutable composite types, x === y is true if x and y have the same type – and thus the same structure – and their corresponding components are all recursively ===.
  • For bits types (immutable chunks of data like Int or Float64), x === y is true if x and y contain exactly the same bits.

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

These rules, applied recursively, define the behavior of ===.

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

The == function, on the other hand, is user-definable, and implements "abstract value equality". Overloadability is one key difference:

  • === 不可重载 - 它是具有固定、预定义行为的内置函数.您不能扩展或更改其行为.
  • == 是可重载的——它是具有中缀语法的普通(对于 Julia)泛型函数.它具有后备定义,使其在用户定义的类型上具有有用的默认行为,但您可以通过向 == 为您的类型添加新的、更具体的方法来更改它.
  • The === is not overloadable – it is a builtin function with fixed, pre-defined behavior. You cannot extend or change its behavior.
  • The == is overloadable – it is a normal (for Julia) generic function with infix syntax. It has fallback definitions that give it useful default behavior on user-defined types, but you can change that as you see fit by adding new, more specific methods to == for your types.

提供更多关于 == 对于内置类型的行为方式以及当人们扩展它时它对于用户定义类型的行为方式的详细信息,来自 文档:

To provide more detail about how == behaves for built-in types and how it should behave for user-defined types when people extend it, from the docs:

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

For example, all numeric types are compared by numeric value, ignoring type. Strings are compared as sequences of characters, ignoring encoding.

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

You can think of this as "intuitive equality". If two numbers are numerically equal, they are ==:

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

julia> 0.5 == 1/2 == 1//2
true

注意,但是 == 实现了精确的数值相等:

Note, however that == implements exact numerical equality:

julia> 2/3 == 2//3
false

这些值不相等,因为 2/3 是浮点值 0.6666666666666666,它是最接近数学值 2 的 Float64/3(或在 Julia 表示法中表示有理值,2//3),但 0.6666666666666666 并不完全等于 2/3.此外,==

These values are unequal because 2/3 is the floating-point value 0.6666666666666666, which is the closest Float64 to the mathematical value 2/3 (or in Julia notation for a rational values, 2//3), but 0.6666666666666666 is not exactly equal to 2/3. Moreover, ==

遵循 IEEE 754 浮点数语义.

Follows IEEE 754 semantics for floating-point numbers.

这包括一些可能意想不到的属性:

This includes some possibly unexpected properties:

  • 有明显的正负浮点零(0.0-0.0):它们是 ==,尽管它们的行为不同,因此不是 ===.
  • 有许多不同的非数字 (NaN) 值:它们不是 == 对自己、彼此或任何其他值;它们各自是 === 对自己,但不是 !== 因为它们有不同的位.
  • There are distinct positive and negative floating-point zeros (0.0 and -0.0): they are ==, even though they behave differently and are thus not ===.
  • There are many different not-a-number (NaN) values: they are not == to themselves, each other, or any other value; they are each === to themselves, but not !== to each other since they have different bits.

例子:

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 标准.

This is kind of confusing, but that's the IEEE standard.

此外,== 的文档还声明:

Further, the docs for == also state:

集合通常应该通过对所有内容递归调用 == 来实现 ==.

Collections should generally implement == by calling == recursively on all contents.

因此,== 给出的值相等概念递归地扩展到集合:

Thus, the notion of value equality as given by == is extended recursively to collections:

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

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

Accordingly, this inherits the foibles of scalar == comparisons:

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

julia> a == a
false

另一方面,=== 比较总是测试对象身份,因此即使两个数组具有相同的类型并包含相同的值,它们也只有在它们是相同的数组时才相等:

The === comparison, on the other hand always tests object identity, so even if two arrays have the same type and contain identical values, they are only equal if they are the same array:

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 不是 === 的原因是即使它们当前碰巧这里包含相同的数据,因为它们是可变的而不是同一个对象,你可以改变其中一个,然后很明显它们是不同的:

The reason that a and b are not === is that even though they currently happen to contain the same data here, since they are mutable and not the same object, you could mutate one of them and then it would become apparent that they are different:

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 是不同的对象.同样的逻辑不适用于不可变对象:如果它们包含相同的数据,只要它们具有相同的值,它们就无法区分.因此,不可变值摆脱了绑定到特定位置的束缚,这也是编译器能够如此有效地优化不可变值使用的原因之一.

Thus you can tell that a and b are different objects through mutation. The same logic doesn't apply to immutable objects: if they contain the same data, they are indistinguishable as long as they have the same value. Thus, immutable values are freed from the being tied to a specific location, which is one of the reasons that compilers are able to optimize uses of immutable values so effectively.

另请参阅:

这篇关于“=="和“=="有什么区别?和“==="Julia中的比较运算符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆