如何以最小增量改变double

时间:2010-10-10 13:16:36

标签: java double ieee-754

有什么东西坏了,或者我不明白发生了什么?

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]

5 个答案:

答案 0 :(得分:8)

一般的想法是首先将double转换为其长表示(使用doubleToLongBits中的getRealBinary),将长度增加1,最后将新long转换为double它代表通过longBitsToDouble

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

答案 1 :(得分:7)

浮点数不会像整数类型那样在数字线上均匀分布。当你接近无限时,它们在0附近更密集地堆积并且相隔很远。因此,没有常量可以添加到浮点数以获得下一个浮点数。

答案 2 :(得分:4)

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

建议阅读:http://en.wikipedia.org/wiki/Machine_epsilon

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

答案 3 :(得分:3)

从Java 1.8开始,java.lang.Math.nextUp(double)完全符合您的要求。还有java.lang.Math.nextDown(double)的对面。

答案 4 :(得分:0)

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