应该这样做。对于十进制,我利用 Jon Skeet 的初始方法生成随机 decimals(无约束)。对于long,我提供了一种生成随机非负longs 的方法,然后使用该方法在随机范围内创建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;
}
}