【问题标题】:How to alter double by its smallest increment如何通过最小增量改变 double
【发布时间】:2017-05-17 21:30:25
【问题描述】:

是有什么东西坏了还是我不明白发生了什么?

static String getRealBinary(double val) {
    long tmp = Double.doubleToLongBits(val);
    StringBuilder sb = new StringBuilder();

    for (long n = 64; --n > 0; tmp >>= 1)
        if ((tmp & 1) == 0)
            sb.insert(0, ('0'));
        else
            sb.insert(0, ('1'));

    sb.insert(0, '[').insert(2, "] [").insert(16, "] [").append(']');
    return sb.toString();
}

public static void main(String[] argv) {
    for (int j = 3; --j >= 0;) {
        double d = j;
        for (int i = 3; --i >= 0;) {
            d += Double.MIN_VALUE;
            System.out.println(d +getRealBinary(d));
        }
    }
}

有输出:

2.0[1] [00000000000] [000000000000000000000000000000000000000000000000000]
2.0[1] [00000000000] [000000000000000000000000000000000000000000000000000]
2.0[1] [00000000000] [000000000000000000000000000000000000000000000000000]
1.0[0] [11111111110] [000000000000000000000000000000000000000000000000000]
1.0[0] [11111111110] [000000000000000000000000000000000000000000000000000]
1.0[0] [11111111110] [000000000000000000000000000000000000000000000000000]
4.9E-324[0] [00000000000] [000000000000000000000000000000000000000000000000001]
1.0E-323[0] [00000000000] [000000000000000000000000000000000000000000000000010]
1.5E-323[0] [00000000000] [000000000000000000000000000000000000000000000000011]

【问题讨论】:

  • 你想做什么?你有什么问题?
  • 我的问题是:“如何通过最小增量改变 double”,这是我失败的努力。
  • 如果你想做最小的增量,为什么不直接编辑这些位呢,因为 MIN_VALUE 很小(真的很小)所以 0+真的很小 = 真的很小,但是 2+ 真的会失败小〜= 2它是因为浮动点,min_value尽可能远离点,而对于两个它在中间的某个地方,左边输了。你可以在点后看到它大约 300 位的差异应该是,而 double 只存储大约 15-20 位有效数字。
  • 自我说明:'--n > 0;'应该是'--n >= 0;'。

标签: java double ieee-754


【解决方案1】:

一般的想法是首先将双精度转换为它的长表示(使用doubleToLongBits,就像你在getRealBinary中所做的那样),将该长加1,最后将新的长转换回它通过@表示的双精度987654324@.

编辑:Java(从 1.5 开始)提供 Math.ulp(double),我猜您可以使用它直接计算下一个更高的值:x + Math.ulp(x)

【讨论】:

【解决方案2】:

浮点数不像整数类型那样均匀地分布在数轴上。当你接近无穷大时,它们在 0 附近更密集,并且相距很远。因此,没有常数可以添加到浮点数以得到下一个浮点数。

【讨论】:

  • 怎么会这样?我们有一个尾数和一个指数。也不赞成 0。
  • @TonyEnnis:指数就是这样——一个指数。稍微简化一下,浮点数的值类似于mantissa * 2^exponent。也就是说,改变尾数改变结果数的量完全取决于指数的值。指数越低,变化越小。
【解决方案3】:

您的代码格式不正确。您尝试添加最小双精度值并期望结果与原始值不同。问题是 double.MinValue 太小以至于结果被四舍五入并且不会受到影响。

推荐阅读:http://en.wikipedia.org/wiki/Machine_epsilon

在 Wikipedia 文章中也有 Java 代码。 Epsilon 根据定义是最小的数,例如 (X + eps * X != X),而 eps*X 被称为“相对-epsilon”

【讨论】:

    【解决方案4】:

    从 Java 1.8 开始,java.lang.Math.nextUp(double) 就在做你想做的事。还有对面的java.lang.Math.nextDown(double)

    【讨论】:

      【解决方案5】:

      如果您想使用 BigDecimal 类,还有 BigDecimal.ulp() 方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-03-14
        • 1970-01-01
        • 2023-03-19
        • 1970-01-01
        • 2014-02-07
        • 2010-09-29
        • 2017-01-03
        • 1970-01-01
        相关资源
        最近更新 更多