簡體   English   中英

證明 A == B, B==C, A != C

[英]Prove that A == B, B==C, A != C

是否存在傳遞定律不成立的對象或原始類型? 例如

A == B, B == C 但 A != B

我不是在談論 equals() 方法。 我對 == 操作感興趣

我們能證明這一點嗎?

干得好。 A==BB==C導致Float被提升為浮點數,所以==返回 true。 但是, 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在這里並不特殊,它可以很容易地是IntegerBoolean

以下是語言規范中的相關部分:

15.21.1. 數值相等運算符 == 和 !=

如果相等運算符的操作數都是數字類型,或者一個是數字類型而另一個可轉換(第 5.1.8 節)為數字類型,則對操作數執行二進制數字提升(第 5.6.2 節)。

15.21.3. 引用相等運算符 == 和 !=

如果相等運算符的操作數都是引用類型或空類型,則該操作是對象相等。

這是第二個反例,這次使用的事實是,比較longfloat是使用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 是雙擴展指數值(與它們最近的雙精度值 B 相同),那么當計算 A==B 和 B==C 時,語言實現可能會選擇舍入 A 和 C到最接近的雙精度值(即 B)。 當執行A == C中,它也可以同樣不會選擇圓。 必須在未標記為 FP-strict 的上下文中進行比較

本質上,“5.1.13. 值集轉換”為 Java 提供了一組有限的實現定義的非 FP 嚴格浮點/雙精度計算行為,並且可以(至少在理論上)利用這一點來找到相等的反例傳遞性。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM