注意:为简洁起见,下文将不区分随机性和伪随机性。此外,在这种情况下,约束 表示在给定的最小值和最大值之间)
System.Random
类提供整数、 double 和字节数组的随机生成。
使用 Random.Next,可以轻松生成 Boolean、Char、(S)Byte、(U)Int16、(U)Int32 类型的随机约束值。使用 Random.NextDouble()
,可以类似地生成 Double 和 Single 类型的约束值(据我对这种类型的理解)。随机字符串生成(给定长度和字母)has also been tackled before .
考虑剩余的原始数据类型(不包括 Object):Decimal 和 (U)Int64。它们的随机生成也已得到解决(Decimal、(U)Int64 使用 Random.NextBytes()
),但在受约束时没有。理论上可以使用拒绝采样(即循环直到生成的值在所需范围内),但这显然不是一个实用的解决方案。规范化 NextDouble()
将不起作用,因为它没有足够的有效数字。
简而言之,我要求正确实现以下功能:
long NextLong(long min, long max)
long NextDecimal(decimal min, decimal max)
请注意,由于 System.DateTime
基于 ulong,因此第一个函数也将允许随机约束生成此类结构(类似于 here ,仅以滴答而不是分钟为单位).
最佳答案
这应该可以做到。对于十进制,我使用 Jon Skeet 的初始方法来生成随机 decimal
(无约束)。对于 long
,我提供了一种生成随机非负 long
的方法,然后用于在随机范围内创建 a 值。
请注意,对于 decimal
,生成的分布不是 [minValue, maxValue]
上的均匀分布。它只是在 [minValue, maxValue]
范围内的所有小数位表示上是统一的。如果不使用拒绝抽样,我看不到解决这个问题的简单方法。
对于 long
,生成的分布在 [minValue, maxValue)
上是均匀的。
static class RandomExtensions {
static int NextInt32(this Random rg) {
unchecked {
int firstBits = rg.Next(0, 1 << 4) << 28;
int lastBits = rg.Next(0, 1 << 28);
return firstBits | lastBits;
}
}
public static decimal NextDecimal(this Random rg) {
bool sign = rg.Next(2) == 1;
return rg.NextDecimal(sign);
}
static decimal NextDecimal(this Random rg, bool sign) {
byte scale = (byte)rg.Next(29);
return new decimal(rg.NextInt32(),
rg.NextInt32(),
rg.NextInt32(),
sign,
scale);
}
static decimal NextNonNegativeDecimal(this Random rg) {
return rg.NextDecimal(false);
}
public static decimal NextDecimal(this Random rg, decimal maxValue) {
return (rg.NextNonNegativeDecimal() / Decimal.MaxValue) * maxValue; ;
}
public static decimal NextDecimal(this Random rg, decimal minValue, decimal maxValue) {
if (minValue >= maxValue) {
throw new InvalidOperationException();
}
decimal range = maxValue - minValue;
return rg.NextDecimal(range) + minValue;
}
static long NextNonNegativeLong(this Random rg) {
byte[] bytes = new byte[sizeof(long)];
rg.NextBytes(bytes);
// strip out the sign bit
bytes[7] = (byte)(bytes[7] & 0x7f);
return BitConverter.ToInt64(bytes, 0);
}
public static long NextLong(this Random rg, long maxValue) {
return (long)((rg.NextNonNegativeLong() / (double)Int64.MaxValue) * maxValue);
}
public static long NextLong(this Random rg, long minValue, long maxValue) {
if (minValue >= maxValue) {
throw new InvalidOperationException();
}
long range = maxValue - minValue;
return rg.NextLong(range) + minValue;
}
}
关于c# - (U)Int64 和 Decimal 的(伪)随机约束值的生成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2000311/