代码之家  ›  专栏  ›  技术社区  ›  Kelly S. French

这两种方法在Java中是等价的吗?

  •  1
  • Kelly S. French  · 技术社区  · 14 年前

    替代措辞 导致不同的双精度值?(见下面乔恩·斯凯特的评论)

    这个 SO question 关于Java中的最小双精度值,有一些答案在我看来是等价的。 Jon Skeet answer Richard's answer .

    乔恩的回答是:

    double d = // your existing value;
    long bits = Double.doubleToLongBits(d);
    bits++;
    d = Double.longBitsToDouble();
    

    理查兹的回答提到了JavaDoc Double.MIN_VALUE

    double型的正非零值, 2-1074. 它等于十六进制 浮点文字 到 Double.longBitsToDouble(0x1L) .

    我的问题是,你怎么样 Double.logBitsToDouble(0x1L) 和乔恩的不同 bits++;

    添加 双最小值两倍的值, 以及递增位模式 代表双重身份。他们是 浮点数 被储存。如果你想添加一个 从一个小数字到一个很大的数字, 最接近的结果与 原版。将1添加到当前 然而,位模式总是 点值,尽可能小

    我看不出Jon用加法来增加一个长的“bits++”的方法有什么不同双最小值. 他们什么时候会产生不同的结果?

    我编写了以下代码来测试这些差异。也许有人可以提供更多/更好的样本双数,或者使用循环来查找存在差异的数字。

        double d = 3.14159269123456789; // sample double
        long bits = Double.doubleToLongBits(d);
        long bitsBefore = bits;
        bits++;
        long bitsAfter = bits;
        long bitsDiff = bitsAfter - bitsBefore;
        long bitsMinValue = Double.doubleToLongBits(Double.MIN_VALUE);
        long bitsSmallValue = Double.doubleToLongBits(Double.longBitsToDouble(0x1L));
    
        if (bitsMinValue == bitsSmallValue)
        {
            System.out.println("Double.doubleToLongBits(0x1L) is same as Double.doubleToLongBits(Double.MIN_VALUE)");           
        }        
    
        if (bitsDiff == bitsMinValue)
        {
            System.out.println("bits++ increments the same amount as Double.MIN_VALUE");
        }
    
        if (bitsDiff == bitsMinValue)
        {
            d = d + Double.MIN_VALUE;
            System.out.println("Using Double.MIN_VALUE");
        }
        else
        {
            d = Double.longBitsToDouble(bits);
            System.out.println("Using doubleToLongBits/bits++");
        }
    
        System.out.println("bits before: " + bitsBefore);   
        System.out.println("bits after: " + bitsAfter);
        System.out.println("bits diff: " + bitsDiff);   
        System.out.println("bits Min value: " + bitsMinValue);
        System.out.println("bits Small value: " + bitsSmallValue);  
    

    输出:

    Double.doubleToLongBits(Double.longBitsToDouble(0x1L)) is same as Double.doubleToLongBits(Double.MIN_VALUE)
    bits++ increments the same amount as Double.MIN_VALUE
    Using doubleToLongBits/bits++
    bits before: 4614256656636814345
    bits after: 4614256656636814346
    bits diff: 1
    bits Min value: 1
    bits Small value: 1
    
    2 回复  |  直到 7 年前
        1
  •  7
  •   Jon Skeet    14 年前

    好吧,让我们这样想象,坚持十进制数字。假设您有一个浮点数类型,它允许您表示5个十进制数字,指数为0到3之间的数字,将结果乘以1、10、100或1000。

    现在,当你把1加到50000000时会发生什么?你不能代表50000001…500000000之后的下一个可代表数字是50001000。所以如果你尝试把它们加在一起,结果就是最接近“真实”结果的值——仍然是500000000。就像是加了 Double.MIN_VALUE 到一个大的 double .

    你看到他们有什么不同吗?


    下面是一个具体的例子:

    public class Test{
        public static void main(String[] args) {
            double before = 100000000000000d;
            double after = before + Double.MIN_VALUE;
            System.out.println(before == after);
    
            long bits = Double.doubleToLongBits(before);
            bits++;
            double afterBits = Double.longBitsToDouble(bits);
            System.out.println(before == afterBits);
            System.out.println(afterBits - before);
        }
    }
    

    这两种方法都有大量的尝试。输出为:

    true
    false
    0.015625
    

    • 添加 双最小值
    • 递增位 产生影响
    • 两者的区别 afterBits before 为0.015625 许多的 大于 双最小值
        2
  •  3
  •   Matthew Flaschen    14 年前

    正如乔恩所说:

    “如果你再加一点 差别可能很小 最接近的结果与 “原件。”

    例如:

    // True:
    (Double.MAX_VALUE + Double.MIN_VALUE) == Double.MAX_VALUE
    // False:
    Double.longBitsToDouble(Double.doubleToLongBits(Double.MAX_VALUE) + 1) == Double.MAX_VALUE)
    

    MIN_VALUE 是最小的可表示的正双精度,但这当然并不意味着将其与任意双精度相加会导致不相等的双精度。