有人可以验证这种方法.我需要在两个长度范围内的长型号码.我使用返回int的.NET Random.Next(min,max)函数.如果我将long除以2,生成随机数并最终再乘以2,我的推理是否正确?或者我太热情......我明白我的随机解决方案会减少但是还有其他错误导致没有这样的随机数.
long min = st.MinimumTime.Ticks; //long is Signed 64-bit integer
long max = st.MaximumTime.Ticks;
int minInt = (int) (min / 2); //int is Signed 64-bit integer
int maxInt = (int) (max / 2); //int is Signed 64-bit integer
Random random = new Random();
int randomInt = random.Next(minInt, maxInt);
long randomLong = (randomInt * 2);
Run Code Online (Sandbox Code Playgroud)
Dyp*_*ppl 82
为什么不直接生成两个随机Int32
值并从中生成一个Int64
?
long LongRandom(long min, long max, Random rand) {
long result = rand.Next((Int32)(min >> 32), (Int32)(max >> 32));
result = (result << 32);
result = result | (long)rand.Next((Int32)min, (Int32)max);
return result;
}
Run Code Online (Sandbox Code Playgroud)
对不起,我忘了第一次添加边界.添加min
和max
参数.你可以这样测试:
long r = LongRandom(100000000000000000, 100000000000000050, new Random());
Run Code Online (Sandbox Code Playgroud)
的值r
将处于期望的范围内.
编辑:上面的实现是有缺陷的.为了避免有符号无符号问题,生成4个16位整数而不是2个32位整数可能是值得的.但是在这一点上解决方案失去了它的优雅,所以我认为最好坚持使用Random.NextBytes
版本:
long LongRandom(long min, long max, Random rand) {
byte[] buf = new byte[8];
rand.NextBytes(buf);
long longRand = BitConverter.ToInt64(buf, 0);
return (Math.Abs(longRand % (max - min)) + min);
}
Run Code Online (Sandbox Code Playgroud)
在价值分布方面看起来相当不错(通过我运行的非常简单的测试来判断).
Blu*_*eft 28
这里的一些其他答案有两个问题:具有模偏差,并且无法正确处理其值max = long.MaxValue
.(马丁的答案既没有问题,但他的代码在大范围内是不合理的慢.)
以下代码将解决所有这些问题:
//Working with ulong so that modulo works correctly with values > long.MaxValue
ulong uRange = (ulong)(max - min);
//Prevent a modolo bias; see https://stackoverflow.com/a/10984975/238419
//for more information.
//In the worst case, the expected number of calls is 2 (though usually it's
//much closer to 1) so this loop doesn't really hurt performance at all.
ulong ulongRand;
do
{
byte[] buf = new byte[8];
random.NextBytes(buf);
ulongRand = (ulong)BitConverter.ToInt64(buf, 0);
} while (ulongRand > ulong.MaxValue - ((ulong.MaxValue % uRange) + 1) % uRange);
return (long)(ulongRand % uRange) + min;
Run Code Online (Sandbox Code Playgroud)
以下完整记录的类可以放入您的代码库中,以轻松实现上述解决方案并且无需大脑.与Stackoverflow上的所有代码一样,它在CC归属下获得许可,因此您可以随意使用它,无论您想要什么.
using System;
namespace MyNamespace
{
public static class RandomExtensionMethods
{
/// <summary>
/// Returns a random long from min (inclusive) to max (exclusive)
/// </summary>
/// <param name="random">The given random instance</param>
/// <param name="min">The inclusive minimum bound</param>
/// <param name="max">The exclusive maximum bound. Must be greater than min</param>
public static long NextLong(this Random random, long min, long max)
{
if (max <= min)
throw new ArgumentOutOfRangeException("max", "max must be > min!");
//Working with ulong so that modulo works correctly with values > long.MaxValue
ulong uRange = (ulong)(max - min);
//Prevent a modolo bias; see https://stackoverflow.com/a/10984975/238419
//for more information.
//In the worst case, the expected number of calls is 2 (though usually it's
//much closer to 1) so this loop doesn't really hurt performance at all.
ulong ulongRand;
do
{
byte[] buf = new byte[8];
random.NextBytes(buf);
ulongRand = (ulong)BitConverter.ToInt64(buf, 0);
} while (ulongRand > ulong.MaxValue - ((ulong.MaxValue % uRange) + 1) % uRange);
return (long)(ulongRand % uRange) + min;
}
/// <summary>
/// Returns a random long from 0 (inclusive) to max (exclusive)
/// </summary>
/// <param name="random">The given random instance</param>
/// <param name="max">The exclusive maximum bound. Must be greater than 0</param>
public static long NextLong(this Random random, long max)
{
return random.NextLong(0, max);
}
/// <summary>
/// Returns a random long over all possible values of long (except long.MaxValue, similar to
/// random.Next())
/// </summary>
/// <param name="random">The given random instance</param>
public static long NextLong(this Random random)
{
return random.NextLong(long.MinValue, long.MaxValue);
}
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
Random random = new Random();
long foobar = random.NextLong(0, 1234567890L);
Run Code Online (Sandbox Code Playgroud)
age*_*t-j 26
这通过使用随机字节创建随机Int64,如果数字超出安全范围,则通过重试避免模偏.
static class RandomExtensions
{
public static long RandomLong(this Random rnd)
{
byte[] buffer = new byte[8];
rnd.NextBytes (buffer);
return BitConverter.ToInt64(buffer, 0);
}
public static long RandomLong(this Random rnd, long min, long max)
{
EnsureMinLEQMax(ref min, ref max);
long numbersInRange = unchecked(max - min + 1);
if (numbersInRange < 0)
throw new ArgumentException("Size of range between min and max must be less than or equal to Int64.MaxValue");
long randomOffset = RandomLong(rnd);
if (IsModuloBiased(randomOffset, numbersInRange))
return RandomLong(rnd, min, max); // Try again
else
return min + PositiveModuloOrZero(randomOffset, numbersInRange);
}
static bool IsModuloBiased(long randomOffset, long numbersInRange)
{
long greatestCompleteRange = numbersInRange * (long.MaxValue / numbersInRange);
return randomOffset > greatestCompleteRange;
}
static long PositiveModuloOrZero(long dividend, long divisor)
{
long mod;
Math.DivRem(dividend, divisor, out mod);
if(mod < 0)
mod += divisor;
return mod;
}
static void EnsureMinLEQMax(ref long min, ref long max)
{
if(min <= max)
return;
long temp = min;
min = max;
max = temp;
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个利用其他答案的解决方案Random.NextBytes
,但也要注意边界情况.我把它构建为一组扩展方法.此外,我已经考虑了模偏差,通过采样另一个落在范围之外的随机数.
我的一个抱怨(至少对于我试图使用它的情况)是最大值通常是独占的,所以如果你想掷骰子,你会做类似的事情Random.Next(0,7)
.但是,这意味着你永远无法得到这个过载返回.MaxValue
的数据类型(int
,long
,ulong
,什么具备的,你).因此,我添加了一个inclusiveUpperBound
标志来切换此行为.
public static class Extensions
{
//returns a uniformly random ulong between ulong.Min inclusive and ulong.Max inclusive
public static ulong NextULong(this Random rng)
{
byte[] buf = new byte[8];
rng.NextBytes(buf);
return BitConverter.ToUInt64(buf, 0);
}
//returns a uniformly random ulong between ulong.Min and Max without modulo bias
public static ulong NextULong(this Random rng, ulong max, bool inclusiveUpperBound = false)
{
return rng.NextULong(ulong.MinValue, max, inclusiveUpperBound);
}
//returns a uniformly random ulong between Min and Max without modulo bias
public static ulong NextULong(this Random rng, ulong min, ulong max, bool inclusiveUpperBound = false)
{
ulong range = max - min;
if (inclusiveUpperBound)
{
if (range == ulong.MaxValue)
{
return rng.NextULong();
}
range++;
}
if (range <= 0)
{
throw new ArgumentOutOfRangeException("Max must be greater than min when inclusiveUpperBound is false, and greater than or equal to when true", "max");
}
ulong limit = ulong.MaxValue - ulong.MaxValue % range;
ulong r;
do
{
r = rng.NextULong();
} while(r > limit);
return r % range + min;
}
//returns a uniformly random long between long.Min inclusive and long.Max inclusive
public static long NextLong(this Random rng)
{
byte[] buf = new byte[8];
rng.NextBytes(buf);
return BitConverter.ToInt64(buf, 0);
}
//returns a uniformly random long between long.Min and Max without modulo bias
public static long NextLong(this Random rng, long max, bool inclusiveUpperBound = false)
{
return rng.NextLong(long.MinValue, max, inclusiveUpperBound);
}
//returns a uniformly random long between Min and Max without modulo bias
public static long NextLong(this Random rng, long min, long max, bool inclusiveUpperBound = false)
{
ulong range = (ulong)(max - min);
if (inclusiveUpperBound)
{
if (range == ulong.MaxValue)
{
return rng.NextLong();
}
range++;
}
if (range <= 0)
{
throw new ArgumentOutOfRangeException("Max must be greater than min when inclusiveUpperBound is false, and greater than or equal to when true", "max");
}
ulong limit = ulong.MaxValue - ulong.MaxValue % range;
ulong r;
do
{
r = rng.NextULong();
} while(r > limit);
return (long)(r % range + (ulong)min);
}
}
Run Code Online (Sandbox Code Playgroud)
小智 5
private long randomLong()
{
Random random = new Random();
byte[] bytes = new byte[8];
random.NextBytes(bytes);
return BitConverter.ToInt64(bytes, 0);
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
52510 次 |
最近记录: |