随机生成跨越整个有效浮点数的浮点数

时间:2014-02-12 16:37:50

标签: java random java-7

作为random testing的一部分,我希望生成跨越整个有效浮点数的随机浮点数(但不包括+/-无穷大和NaN)。我想要非常非常大的数字和小数字,无论是积极的还是消极的。

这就是我正在做的事情:

Random r = new Random();
float random_value = (r.nextFloat() - 0.5f) * Float.MAX_VALUE;

这似乎应该理论工作,但它只会产生非常大的值。 (即在10 37 - 10 38 的范围内,正面和负面)

有什么建议吗?

4 个答案:

答案 0 :(得分:2)

您的代码应创建均匀分布的float值,即纯数学意义上的均匀分布。然而,这些值中的大部分将在10 37 -10 38 范围内,这仅仅是因为该范围内的数学值多于较低的日常值范围。在实域中,10 37 -10 38 范围内的值的10倍,因为10 36 -10 37 ,10 36 -10 37 范围内的值的10倍,因为10 35 -10 36

我认为您想要的是一个完全随机的float值,其范围仅在有效 float域中。因为float由指数和尾数指定,所以在给定范围内有多少值可用的限制因素受精度限制,而不是有多少数学值可用。具体而言,floata之间的b值与2 * a2 * b之间的float值完全相同,前提是所有值都在intfloat之间{1}}域名。

所有可能的NaN值与所有可能的int值(包括无穷大和int)之间存在一对一的对应关系,因为两种基本类型都由32位表示

在所有可能的int值(正数,0和负数)中选择一个随机float值,并将long位表示转换为您想要的int的相应位表示。您必须选择随机NaN并向下投放到Random rnd = new Random(); float randomFloat = 0.0f; do { // downcast will cover negative int value range. int randomInt = (int) rnd.nextLong(1L << 32); float randomFloat = Float.intBitsToFloat(randomInt); // Discard infinities and NaNs. } while (randomFloat == Float.NEGATIVE_INFINITY || randomFloat == Float.POSITIVE_INFINITY || Float.isNaN(randomFloat)); 。如果您随机获得无穷大或{{1}},请再试一次。

{{1}}

答案 1 :(得分:1)

通过使用位而不是算术生成浮点数,可以获得均匀分布。

这可能是一个选择:

public static float randomFloat() {
    // Generate a random integer. These are uniform over the 32 bit words
    Random r = new Random();
    int intBits = r.nextInt();

    // Make a float from the integer's bits
    float f = Float.intBitsToFloat(intBits);

    // Handle non-numeric cases
    if (Float.isInfinite(f) || Float.isNaN(f)) {
        // Only happens ~ 1/250 times
        return randomFloat();
    } else {
        return f;
    }
}

答案 2 :(得分:0)

你可能会遇到精确问题。尝试以双精度进行乘法,然后逐渐转换为浮点数。

float random_value = (float)((r.nextDouble() - 0.5) * Float.MAX_VALUE);

答案 3 :(得分:0)

首先,您要生成介于-1和1之间的随机浮点数。要执行此操作:

Random r = new Random();
float random_value = r.nextFloat() * 2 - 1

然后缩放:

Random r = new Random();
float random_value = (r.nextFloat() * 2 - 1) * Float.MAX_VALUE