代码之家  ›  专栏  ›  技术社区  ›  Chris Harcourt

当包装在双实例中时,double.nan为什么等于自身?

  •  10
  • Chris Harcourt  · 技术社区  · 16 年前

    this question 我学会了双重意义。南不等于自己。

    我为自己验证了这一点,注意到如果用双实例包装double.nan,则情况并非如此。例如:

    public class DoubleNaNTest {
        public static void main(String[] args) {
            double primitive = Double.NaN;
            Double object = new Double(primitive);
    
            // test 1 - is the primitive is equal to itself?
            boolean test1 = primitive == primitive;
    
            // test 2 - is the object equal to itself?
            boolean test2 = object.equals(object);
    
            // test 3 - is the double value of the object equal to itself?
            boolean test3 = object.doubleValue() == object.doubleValue();
    
            System.out.println("Test 1 = " + test1);
            System.out.println("Test 2 = " + test2);
            System.out.println("Test 3 = " + test3);
        }
    }
    

    输出:

    Test 1 = false
    Test 2 = true
    Test 3 = false
    

    在我看来,这三个测试的评估结果都应该是错误的,因为这三个操作都是等效的(如果您使用的是double.nan以外的东西)。

    有人能解释一下这是怎么回事吗?

    3 回复  |  直到 13 年前
        1
  •  11
  •   Stephen C    16 年前

    发生什么事了? equals 方法故意偏离IEE浮点。从JavaDoc中引用 equals(Object) 方法 java.lang.Double .

    但是,有两个例外:

    • 如果d1和d2都表示double.nan,则等号法 即使返回真 double.nan==double.nan具有值 错误的。
    • 如果d1代表+0.0,而d2代表-0.0,反之亦然,则
      相等测试的值为false,偶数
      尽管+0.0=-0.0的值为真。

    此定义允许哈希表 正确操作。

    结果是,如果希望100%IEE浮点兼容性,则需要显式取消对 java.lang.Double 实例并比较结果 double 价值观。

        2
  •  5
  •   DigitalRoss    16 年前

    所以哈希表可以正常工作

    他们故意偏离了IEEE的方式,这样哈希表就可以工作了。

    你可以得到故事的一部分 in the api docs . 故事的其余部分是:从对象继承的每个类(即所有类)都有一个契约来维护对象不变量。这个契约的存在是为了让图书馆的其余部分能够实现所有这些好的集合和事情。没有什么能真正阻止你破坏它,但是你不能确定拿走物体的东西会起作用。

        3
  •  0
  •   supercat    13 年前

    如果一个有两个不变的对象定义 Equals 当一个对象中的每个字段报告自身时返回true Equal 到另一个对象中对应的字段,如果使用对象的代码中没有一个关心引用相等,那么应该可以用对另一个对象的引用替换对一个对象的所有引用。如果对象是通过解析从磁盘读取的数据而生成的,并且如果许多对象将进行相同的比较,则将多个不同的实例替换为对一个实例的引用可能会大大提高性能。请注意,这种替换的正确性并不取决于对象是浅不可变还是深不可变,前提是嵌套在对象中的任何可变对象都将报告自己与其他对象不相等。

    对于这样的逻辑来说,重要的是问题对象是完全等效的。每一个物体都必须等于它自己,所以 Double.NaN 必须平等 双南 .完全等效的要求意味着,正零不能报告自己等于负零(因为如果是这样,持有正零的对象的行为可能不同于持有负零的对象)。

    注意,BTW,这是一个.NET与Java不同的区域(一些非等效浮点和 Decimal 值为报表 等于 );在很多方面,我认为.NET是优越的,但这个细节是.NET出错的。