作为random testing的一部分,我希望生成跨越整个有效浮点数的随机浮点数(但不包括+/-无穷大和NaN
)。我想要非常非常大的数字和小数字,无论是积极的还是消极的。
这就是我正在做的事情:
Random r = new Random();
float random_value = (r.nextFloat() - 0.5f) * Float.MAX_VALUE;
这似乎应该理论工作,但它只会产生非常大的值。 (即在10 37 - 10 38 的范围内,正面和负面)
有什么建议吗?
答案 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
由指数和尾数指定,所以在给定范围内有多少值可用的限制因素受精度限制,而不是有多少数学值可用。具体而言,float
和a
之间的b
值与2 * a
和2 * b
之间的float
值完全相同,前提是所有值都在int
和float
之间{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