证明 A == B, B==C, A != C
Prove that A == B, B==C, A != C
是否存在传递法则不成立的对象或原始类型?例如
A == B, B == C 但 A != B
我不是在谈论 equals() 方法。我对 == 操作感兴趣
我们能证明这一点吗?
给你。 A==B
和 B==C
导致 Float
被提升为浮动,因此 ==
returns 为真。但是,A==C
是引用相等,这是错误的。
Float A = new Float(1.0f);
float B = 1.0f;
Float C = new Float(1.0f);
System.out.println(A==B);
System.out.println(B==C);
System.out.println(A==C);
Float
在这里并不特别,它可以很容易地成为 Integer
或 Boolean
.
以下是语言规范中的相关部分:
15.21.1. Numerical Equality Operators == and !=
If the operands of an equality operator are both of numeric type, or
one is of numeric type and the other is convertible (§5.1.8) to
numeric type, binary numeric promotion is performed on the operands
(§5.6.2).
和
15.21.3. Reference Equality Operators == and !=
If the operands of an equality operator are both of either reference
type or the null type, then the operation is object equality.
这是第二个反例,这次使用的是 long
和 float
的比较是使用 float
比较完成的。
long a = 99999999999999L;
float b = 99999999999999.0f;
long c = 99999999999998L;
System.out.println(a==b);
System.out.println(b==c);
System.out.println(a==c);
第三,我认为即使A、B、C是同一类型,理论上也可能存在非传递性。
如果 A 和 C 是 double-extended-exponent values(与它们最近的双精度值 B 具有相同的值),则在计算 A==B 和 B==C 时,语言实现可能会选择将 A 和 C 舍入到它们最接近的双精度值(即 B)。执行A==C时同样可以选择not进行舍入。必须在未标记为 FP-strict
的上下文中进行比较
本质上,“5.1.13. 值集转换”为 Java 非 FP 严格 float/double 计算提供了一组有限的实现定义的行为,并且可以利用这一点(至少理论上)找到相等传递性的反例。
来自 Swift 的是一个非常奇怪的例子。在这里,不是引用语义在起作用,而是嵌套可选的包装程度,以及编译器显式解包该可选的程度,发挥作用:
let a = nil as Int? as Int?? as? Int?
let b = nil as Int? as Int??
let c: Int? = nil
assert(b == a) // passes
assert(c == a && c == nil && a != nil) // passes. wtf
assert(c == b && u == nil && b != nil) // passes. wtf
是否存在传递法则不成立的对象或原始类型?例如
A == B, B == C 但 A != B
我不是在谈论 equals() 方法。我对 == 操作感兴趣
我们能证明这一点吗?
给你。 A==B
和 B==C
导致 Float
被提升为浮动,因此 ==
returns 为真。但是,A==C
是引用相等,这是错误的。
Float A = new Float(1.0f);
float B = 1.0f;
Float C = new Float(1.0f);
System.out.println(A==B);
System.out.println(B==C);
System.out.println(A==C);
Float
在这里并不特别,它可以很容易地成为 Integer
或 Boolean
.
以下是语言规范中的相关部分:
15.21.1. Numerical Equality Operators == and !=
If the operands of an equality operator are both of numeric type, or one is of numeric type and the other is convertible (§5.1.8) to numeric type, binary numeric promotion is performed on the operands (§5.6.2).
和
15.21.3. Reference Equality Operators == and !=
If the operands of an equality operator are both of either reference type or the null type, then the operation is object equality.
这是第二个反例,这次使用的是 long
和 float
的比较是使用 float
比较完成的。
long a = 99999999999999L;
float b = 99999999999999.0f;
long c = 99999999999998L;
System.out.println(a==b);
System.out.println(b==c);
System.out.println(a==c);
第三,我认为即使A、B、C是同一类型,理论上也可能存在非传递性。
如果 A 和 C 是 double-extended-exponent values(与它们最近的双精度值 B 具有相同的值),则在计算 A==B 和 B==C 时,语言实现可能会选择将 A 和 C 舍入到它们最接近的双精度值(即 B)。执行A==C时同样可以选择not进行舍入。必须在未标记为 FP-strict
的上下文中进行比较本质上,“5.1.13. 值集转换”为 Java 非 FP 严格 float/double 计算提供了一组有限的实现定义的行为,并且可以利用这一点(至少理论上)找到相等传递性的反例。
来自 Swift 的是一个非常奇怪的例子。在这里,不是引用语义在起作用,而是嵌套可选的包装程度,以及编译器显式解包该可选的程度,发挥作用:
let a = nil as Int? as Int?? as? Int?
let b = nil as Int? as Int??
let c: Int? = nil
assert(b == a) // passes
assert(c == a && c == nil && a != nil) // passes. wtf
assert(c == b && u == nil && b != nil) // passes. wtf