如何按最小增量更改 double

发布于 2024-09-27 04:26:50 字数 1423 浏览 6 评论 0原文

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

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]

Is something broken or I fail to understand what is happening?

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));
        }
    }
}

With output:

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]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

自由如风 2024-10-04 04:26:51

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

Floating point numbers are not spread out uniformly over the number line like integer types are. They are more densely packed near 0 and very far apart as you approach infinity. Therefore there is no constant that you can add to a floating point number to get to the next floating point number.

×纯※雪 2024-10-04 04:26:51

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

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

维基百科文章也是Java代码。 Epsilon 根据定义是最小的数字,例如 (X + eps * X != X),eps*X 称为“相对 epsilon”

Your code is not well-formed. You try to add the minimum double value and expect the result to be different from the original value. The problem is that double.MinValue is so small that the result is rounded and doesn't get affected.

Suggested reading: http://en.wikipedia.org/wiki/Machine_epsilon

On the Wikipedia article there is the Java code too. Epsilon is by definition the smallest number such as (X + eps * X != X), and eps*X is called "relative-epsilon"

清眉祭 2024-10-04 04:26:51

从 Java 1.8 开始,java.lang.Math.nextUp(double) 完全可以满足您的需求。还有相反的java.lang.Math.nextDown(double)

Since Java 1.8 there is java.lang.Math.nextUp(double) doing exactly what you want. There is also opposite java.lang.Math.nextDown(double).

标点 2024-10-04 04:26:51

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

In case you want to use the BigDecimal class, there is the BigDecimal.ulp() method as well.

若能看破又如何 2024-10-04 04:26:50

总体思路是首先将 double 转换为其 long 表示形式(使用 doubleToLongBits 正如您在 getRealBinary 中所做的那样),将该 long 加 1,最后将新的 long 转换回来通过longBitsToDouble 转换为它所代表的双精度数。

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

The general idea is first convert the double to its long representation (using doubleToLongBits as you have done in getRealBinary), increment that long by 1, and finally convert the new long back to the double it represents via longBitsToDouble.

EDIT: Java (since 1.5) provides Math.ulp(double), which I'm guessing you can use to compute the next higher value directly thus: x + Math.ulp(x).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文