什么是等同和相等之间的区别?

39

我在数学和计算机科学的阅读中看到过几次使用等价符号(基本上是带有三条线的“=”),并且总是习惯将其读作相等。这两个概念之间有什么区别?

这两个符号确实非常相似,但它们代表不同的意义。等号=通常表示两个物体相等,而等价符号 则表示两个物体在某些方面等价或具有相同的属性,但不一定完全相等。 在计算机科学中,等价关系通常指两个对象具有相同的结构或行为。 例如,如果两个算法最终会产生相同的结果,则可以说它们是等价的。


7
我很想用尖酸刻薄的回答“平等==等价”,但是我知道这个回答是错误的,所以它只会被投票淹没。 :) (注:本翻译尽量保留原文的语言风格和幽默感,同时确保翻译准确并易于理解。) - Bill the Lizard
1
Smalltalk区分这两个概念:等价性(==)是测试两个对象是否为同一对象的测试。相等性(=)是测试两个对象是否表示相同组件的测试。(来源:Smalltalk-80蓝皮书,第96页,比较对象 - alexg
这是一个很好的问题,但我认为它太笼统了 - 我必须分别处理数学和形式逻辑,然后针对每种区分两者的编程语言进行处理...有时它们称之为不同的名称,例如“相等”和“身份”。例如,对于C ++-https://www.reddit.com/r/cpp_questions/comments/47k4gj/equality_vs_equivalence/ - 在该语言中,“等价性”没有“运算符”,但它是指在某些排序(内置或自定义)中既不是<也不是>的概念。这是一种用于排序稳定性和算法行为等方面的有用术语。 - Tomasz Gandor
10个回答

19

维基百科:等价关系:

在数学中,等价关系是一个将某个集合内的两个元素“等同”起来的二元关系。设a、b和c为集合X内任意元素,则“a ~ b”或“a ≡ b”表示a等价于b。

等价关系“~”具有自反性、对称性和传递性。

换句话说,等号就是等价关系的一种实例。

编辑:这看似简单的自反性、对称性和传递性标准并不总是显然的。例如,可参考Bloch著《Effective Java》第二版35页。

public final class CaseInsensitiveString {
...
    // broken
    @Override public boolean equals(Object o) {
        if (o instance of CaseInsensitiveString)
            return s.equalsIgnoreCase(
                ((CaseInsensitiveString) o).s);
        if (o instanceof String) // One-way interoperability!
            return s.equalsIgnoreCase((String) o);
        return false;
    }  
}

上述的等于实现破坏了对称性,因为CaseInsensitiveString知道String类,但是String类不知道CaseInsensitiveString


18

我理解你的问题是关于数学符号表示而不是编程。你所提到的三个等号可以在HTML中写作&equiv;,在LaTeX中写作\equiv

通常情况下,a ≡ b 表示“a被定义为b”或“使a等于b”。

因此,2+2=4,但是φ ≡ (1+sqrt(5))/2。

以下是一个方便的等价表:

Mathematicians      Computer scientists
--------------      -------------------
      =                      ==
      ≡                      =

其他关于等价关系的回答也是正确的,但我认为它们不够常见。还有一种形式为 ≡ b (mod m) 的等式,发音为“a与b在模m意义下同余”,在程序员的术语中可以表示为 mod(a,m) == mod(b,m)。换句话说,在模m的情况下,a和b相等。


1
“a ≡ b”在数学中并不表示“a被定义为b”。 “≡”的意思是“完全等于”,例如“f(x)≡0”表示对于任何x,等式“f(x)= 0”都成立。相比之下,“f(x)= 0”是一个方程,可以找到它的解... - Anton Petrunin
“计算机科学家”下列出的符号在计算机科学领域并不常见,它只用于编程语言中。 - Jonathan
“≡” 的唯一真正含义是:“去查看你的情况下定义的含义。”它可以有太多不同的意思。一个使用它却没有解释它的文本是不正确的。 - Bolpat

14
许多编程语言区分对象的等价性和对象值的等价性。
例如,Ruby有三种不同的测试相等性的方法。首先,equal?会比较两个变量,以查看它们是否指向同一个实例。这相当于在C风格语言中进行检查,以查看2个指针是否指向同一地址。第二种方法,==,测试值的等价性。因此,在这种情况下,3 == 3.0将为真。第三个方法eql?则比较值和类类型。
Lisp也有不同类型的相等性概念,具体取决于您要测试什么。

4
这是一个对程序员来说很实用的描述。等价性指“a类似于b”,而相等性指“a等于b”。 - Josh Petitt

8

在我所见过区分等号和等价的语言中,等号通常表示类型值都相同,而等价则只表示值相同。例如:

int i = 3;
double d = 3.0;

i和d之间具有等价关系,因为它们代表相同的值,但不是相等关系,因为它们具有不同的类型。其他语言可能会对等价关系有不同的理解(比如两个变量是否代表相同的对象)。


7
上面的答案都是正确的/部分正确的,但它们并没有完全解释两者之间的区别。在理论计算机科学(以及数学的其他分支)中,这与逻辑方程式中自由变量的量化有关(当我们同时使用这两种符号时)。
对我来说,最好理解这个差异的方式是:
1.依据定义 A ≡ B 意味着 对于A和B中可能的所有自由变量的值,A = B 或者 A ≡ B <=> [A = B]
2.通过样例 x=2x 当且仅当 x=0 时, x ≡ 2x (实际上当且仅当也等同于 ≡) 因为x不等于2x的所有可能值
我希望这有所帮助。
编辑: 我脑海中出现的另一件事是这两个定义。
A=B被定义为A<=B和A>=B,其中<=(小于等于,不意味着)可以是任何排序关系
A ≡ B被定义为 A <=> B(当且仅当,意味着双方),值得注意的是,演绎也是一种排序关系,因此使用=而不是≡是可能的(但不太精确,常常令人困惑)。
我想结论是,当你看到"="时,你必须根据上下文来确定作者的意图。

4

把它从编程的领域带出去。

  • (31) equal -- (具有与另一个相同的数量、价值或度量; "以平等条件"; "所有人在法律面前都是平等的")

  • equivalent, tantamount -- (本质上相当于某物; "它和黄金一样好"; "一个愿望相当于一条命令"; "他的陈述与承认有罪等同")

至少在我的字典中,“equivalence”表示它是原始物品的足够好的替代,但不一定完全相同,同样,“equality”传达了完全相同的意思。

null == 0   # true , null is equivelant to 0 ( in php ) 
null === 0  # false, null is not equal to 0 ( in php )  

有些人使用≈来表示非相同的值。

4
两者的区别主要在于引入这两个概念的级别不同。'≡'是形式逻辑中的符号,给定两个命题a和b,a ≡ b表示(a => b AND b => a)。
'='则是集合上等价关系的典型例子,并且至少需要一套集合理论。通常,当一个特定的集合被定义时,它会提供一个适当的等价关系概念,以等号的形式表示。例如,当你定义有理数集Q时,你定义等式a/b = c/d(其中a/b和c/d是有理数),当且仅当ad = bc(其中ad和bc是整数,整数的等式概念已经在其他地方定义)。
有时你会发现非正式的符号f(x) ≡ g(x),其中f和g是函数:它意味着f和g具有相同的定义域,对于该定义域中的每个x,f(x) = g(x)(这又是一个等价关系)。最后,有时你会发现≡(或~)作为一个通用符号来表示等价关系。

2

你可能会有两个具有相同真值(等价)的语句或两个相同的语句(等式)。同时,“带三条杠的等号”也可以表示“定义为”。


1
我总是将三条线读作“等同于”。我会使用“:=”表示“定义为”。 - Mitch Wheat

2
第一个问题是,在这种情况下,“平等”和“等价”是什么意思?基本上,上下文可以自由定义这些术语。
从各种定义中我得到的普遍观点是:对于被称为“相等”的值,无论你从哪个值读取,都不应该有任何区别。

违反这一期望的最极端例子是C++:如果x == y的结果为true,则称xy相等,如果!(x < y) && !(y < x)成立,则称xy等价。即使不考虑用户自定义重载操作符,在浮点数(floatdouble)情况下也存在差异:所有的NaN值彼此等价(实际上与任何其他值都等价),但与包括自身在内的任何其他值都不相等,而值-0.0+0.0比较相等(且等价),尽管聪明的人可以区分它们。

在许多情况下,您需要更准确的术语来传达您的意图。给定两个变量xy

  • 身份“相同”用于表示只有一个对象,xy都指向它。通过x做的任何更改都会无意中通过y观察到,反之亦然。在Java中,使用==检查引用类型变量的身份,在C#中使用ReferenceEquals方法。在C++中,如果xy是引用,std::addressof(x) == std::addressof(y)可以使用(而&x == &y大部分情况下也可以工作,但&可以针对用户定义的类型进行自定义)。
  • 按位结构相等用于表示xy的内部表示相同。请注意,当对象在内部可以引用(部分)自身时,按位相等会失效。为了获得预期的含义,在这种情况下,概念必须被细化为:结构相同。在D中,可以通过is来检查按位相等,C提供了memcmp。我不知道有哪种语言内置了结构相等测试。
  • 不可区分性可替代性用于表示值无法通过其公共接口进行区分:如果函数f接受两个参数,并且xy是不可区分的,则调用f(x, y)f(x, x)f(y, y)始终返回不可区分的值 - 除非f直接检查身份(参见上面的要点)或者可能通过改变参数来检查身份。一个例子可以是两个恰好包含不可区分元素的搜索树,但内部树的布局不同。内部树布局是通常无法通过其公共方法观察到的实现细节。
    这也被称为莱布尼兹相等,以哥特弗里德·威廉·莱布尼兹命名,他将相等定义为没有差异。
  • 等价用于表示对象从某种抽象推理中被认为是本质上相同的值。对于可区分的等价值的一个例子是观察浮点数具有与+0.0不同的负零-0.0,例如sign(1/x)对于-0.0+0.0是不同的。许多具有C语言风格(也称为Algol语法)的语言使用==来检查浮点数的等价性。大多数面向对象的语言使用equals(或类似命名的)方法来检查对象的等价性。C#有IEquatable<T>接口,用于指定类上定义了一个标准/规范/默认的等价关系。在Java中,每个类都继承自Object,需要重写equals方法。

正如您所看到的,这些概念变得越来越模糊。检查身份是大多数语言都可以表达的。身份和位等价通常无法被程序员钩取,因为这些概念与解释无关。曾经有一个C++20提案被拒绝了,它将引入最后两个概念作为†和弱相等†。(† 网页已经不存在,404。)原始论文在这里

有一些没有变异的语言,主要是函数式语言,例如Haskell。在那里,等号和等价性之间的区别不太重要,而更倾向于这些词在数学上的使用。(在数学中,一般情况下使用(递归定义的)序列代替重新赋值。)

C语言拥有的一切,同样适用于C++和任何能够使用C功能的语言。关于C#的所有说法也适用于Visual Basic .NET,以及可能是构建在.NET框架上的所有语言。类似地,Java代表了JRE语言,其中还包括Kotlin和Scala。
如果你只想要愚蠢的定义而不是智慧:等价关系是集合上的一个自反、对称和传递的二元关系。等式则是所有这些等价关系的交集。

相等性是所有等价关系的交集。最好称之为“恒等”,因为有些人使用“相等性”一词来包括等价关系。对于等价关系的形式集合论定义并不“愚蠢”,对于集合论目的而言,它非常优雅,例如“一切皆为集合”。 - john
“愚蠢”是指该段落提供了可以放在演示文稿幻灯片上的事实,但没有解释、没有说明甚至没有激励性的例子。 - Bolpat

2

实际上,相等性确实是一种特殊的等价关系。考虑下面这个说法:

0.9999999999999999... = 1

这表明相等只是“字符串数字”上的一个等价关系(严格定义为Z -> {0,...,9}的函数)。从这个例子可以看出,这些等价类甚至不是单元素集合。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接