将双精度型转换为浮点型时的精度问题

问题描述 投票:0回答:1

JDK在

ThreadLocalRandom
中有一个随机方法:

nextDouble(startInclusive, endExclusive)

但没有

float
版本。这里我想要浮动版本,这是我的实现:

public static float nextFloat(float startInclusive, float endExclusive) {
    return (float) nextDouble(startInclusive, endExclusive);
}

我知道浮点数在将 double 转换为 float 时存在精度问题。那么,结果有可能是 float value < startInclusive or >= endExclusive 吗?以及如何解决?

java floating-point double
1个回答
1
投票

事实上,您当前的实现可能会输出等于

endExclusive
的浮点数。假设
next double
返回
d
,它小于
endExclusive
,但由
d
表示的最接近
float
的值仍可能是
endExclusive

在现代版本的 JDK 中,存在

nextFloat
,它采用下界和上限。如果您使用的是旧版本,您可以看看新版本中的
nextFloat
是如何实现的,然后自己做同样的事情。

使用 OpenJDK 主分支中的 RandomSupport.java 中的代码,您可以编写这样一个助手:

public static float nextFloat(Random random, float origin, float bound) {
    if (!(Float.NEGATIVE_INFINITY < origin && origin < bound &&
        bound < Float.POSITIVE_INFINITY)) {
        throw new IllegalArgumentException("Invalid range");
    }
    float r = random.nextFloat();
    if (bound - origin < Float.POSITIVE_INFINITY) {
        r = r * (bound - origin) + origin;
    } else {
        float halfOrigin = 0.5f * origin;
        r = (r * (0.5f * bound - halfOrigin) + halfOrigin) * 2.0f;
    }
    if (r >= bound)
        r = Math.nextDown(bound);
    return r;
}

这使用了无参数的

nextFloat
,它已经存在很长时间了。它返回一个 0 到 1 之间的随机浮点数,代码简单地将 0~1 范围线性映射到我们想要的范围。这个过程也有可能生成一个大于或等于上限的数字,在这种情况下,JDK 似乎只使用小于
bound
(
Math.nextDown
) 的最大浮点数。

© www.soinside.com 2019 - 2024. All rights reserved.