int.MinValue和int.MaxValue之间的随机数(含)

Jon*_*ood 20 .net c# random

这有点令人困惑:Random.Next()具有一个接受最小值和最大值的重载。此重载返回的数字大于或等于最小值(包含)且小于最大值(不含)。

我想包括整个范围,包括最大值。在某些情况下,我可以通过将最大值加一个来完成此操作。但是在这种情况下,最大值可以为int.MaxValue,并且向其中添加一个将无法实现我想要的功能。

那么,有人知道从int.MinValueint.MaxValue包含一个随机数的好技巧吗?

更新:

请注意,下限可以是,int.MinValue但也可以是其他值。如果我知道永远都是这样,int.MinValue那么问题将会更简单。

The*_*ias 12

内部实现Random.Next(int minValue, int maxValue)生成两个样本进行大范围的,等之间的范围Int32.MinValueInt32.MaxValue。对于该NextInclusive方法,我必须使用另一个大范围Next,总共四个样本。因此,性能应与填充4个字节(每个字节一个样本)的缓冲区的版本相当。

public static class RandomExtensions
{
    public static int NextInclusive(this Random random, int minValue, int maxValue)
    {
        if (maxValue == Int32.MaxValue)
        {
            if (minValue == Int32.MinValue)
            {
                var value1 = random.Next(Int32.MinValue, Int32.MaxValue);
                var value2 = random.Next(Int32.MinValue, Int32.MaxValue);
                return value1 < value2 ? value1 : value1 + 1;
            }
            return random.Next(minValue - 1, Int32.MaxValue) + 1;
        }
        return random.Next(minValue, maxValue + 1);
    }

}
Run Code Online (Sandbox Code Playgroud)

一些结果:

new Random(0).NextInclusive(int.MaxValue - 1, int.MaxValue); // returns int.MaxValue
new Random(1).NextInclusive(int.MaxValue - 1, int.MaxValue); // returns int.MaxValue - 1
new Random(0).NextInclusive(int.MinValue, int.MinValue + 1); // returns int.MinValue + 1
new Random(1).NextInclusive(int.MinValue, int.MinValue + 1); // returns int.MinValue
new Random(24917099).NextInclusive(int.MinValue, int.MaxValue); // returns int.MinValue
var random = new Random(784288084);
random.NextInclusive(int.MinValue, int.MaxValue);
random.NextInclusive(int.MinValue, int.MaxValue); // returns int.MaxValue
Run Code Online (Sandbox Code Playgroud)

更新:我的实现在最大可能范围(Int32.MinValue- Int32.MaxValue)上具有中等的性能,因此我想出了一个新的性能,它的运行速度快了4倍。它在我的机器上每秒产生约22,000,000个随机数。我认为它不会比这更快。

public static int NextInclusive(this Random random, int minValue, int maxValue)
{
    if (maxValue == Int32.MaxValue)
    {
        if (minValue == Int32.MinValue)
        {
            var value1 = random.Next() % 0x10000;
            var value2 = random.Next() % 0x10000;
            return (value1 << 16) | value2;
        }
        return random.Next(minValue - 1, Int32.MaxValue) + 1;
    }
    return random.Next(minValue, maxValue + 1);
}
Run Code Online (Sandbox Code Playgroud)

一些结果:

new Random(0).NextInclusive(int.MaxValue - 1, int.MaxValue); // = int.MaxValue
new Random(1).NextInclusive(int.MaxValue - 1, int.MaxValue); // = int.MaxValue - 1
new Random(0).NextInclusive(int.MinValue, int.MinValue + 1); // = int.MinValue + 1
new Random(1).NextInclusive(int.MinValue, int.MinValue + 1); // = int.MinValue
new Random(1655705829).NextInclusive(int.MinValue, int.MaxValue); // = int.MaxValue
var random = new Random(1704364573);
random.NextInclusive(int.MinValue, int.MaxValue);
random.NextInclusive(int.MinValue, int.MaxValue);
random.NextInclusive(int.MinValue, int.MaxValue); // = int.MinValue
Run Code Online (Sandbox Code Playgroud)


Jos*_*son 9

好吧,我有一个窍门。我不确定我会把它描述为“好把戏”,但我觉得它可能有用。

public static class RandomExtensions
{
    public static int NextInclusive(this Random rng, int minValue, int maxValue)
    {
        if (maxValue == int.MaxValue)
        {
            var bytes = new byte[4];
            rng.NextBytes(bytes);
            return BitConverter.ToInt32(bytes, 0);
        }
        return rng.Next(minValue, maxValue + 1);
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,基本上是一种扩展方法,如果上限为,将仅生成四个字节int.MaxValue并将其转换为int,否则只需使用标准Next(int, int)重载即可。

请注意,如果maxValueint.MaxValue它将忽略minValue。猜猜我没有解释这个...


Ale*_*lex 9

不进行强制转换,不long考虑所有边界情况,实现最佳性能。

static class RandomExtension
{
    private static readonly byte[] bytes = new byte[sizeof(int)];

    public static int InclusiveNext(this Random random, int min, int max)
    {
        if (max < int.MaxValue)
            // can safely increase 'max'
            return random.Next(min, max + 1);

        // now 'max' is definitely 'int.MaxValue'
        if (min > int.MinValue)
            // can safely decrease 'min'
            // so get ['min' - 1, 'max' - 1]
            // and move it to ['min', 'max']
            return random.Next(min - 1, max) + 1;

        // now 'max' is definitely 'int.MaxValue'
        // and 'min' is definitely 'int.MinValue'
        // so the only option is
        random.NextBytes(bytes);
        return BitConverter.ToInt32(bytes, 0);
    }
}
Run Code Online (Sandbox Code Playgroud)


Dia*_*cus 5

将范围一分为二,并补偿MaxValue

r.Next(2) == 0 ? r.Next(int.MinValue, 0) : (1 + r.Next(-1, int.MaxValue))
Run Code Online (Sandbox Code Playgroud)

如果我们使范围相等,则通过不同的数学运算可以获得相同的结果。在这里,我们依靠以下事实int.MinValue = -1 - int.MaxValue

r.Next(int.MinValue, 0) - (r.Next(2) == 0 ? 0 : int.MinValue)
Run Code Online (Sandbox Code Playgroud)


Abd*_*tef 1

此方法可以为您提供任何整数限制内的随机整数。如果最大限制小于 int.MaxValue,则它使用普通的 Random.Next(Int32, Int32),但在上限上加 1 以包含其值。如果不是,但下限大于 int.MinValue,则将下限降低 1,将范围移动 1 减去结果加 1。最后,如果两个限制都是 int.MinValue 和 int.MaxValue,它会生成一个随机整数“a”,该整数为 0 或 1,每个整数的概率为 50%,然后生成另外两个整数,第一个整数位于 int.MinValue 和-1(含 -1),2147483648 个值,第二个介于 0 和 int.MaxValue(含)之间,也有 2147483648 个值,并将它们与“a”值一起使用,它会以完全相等的概率选择一个整数。

private int RandomInclusive(int min, int max)
{
    if (max < int.MaxValue)
        return Random.Next(min, max + 1);
    if (min > int.MinValue)
        return Random.Next(min - 1, max) + 1;
    int a = Random.Next(2);
    return Random.Next(int.MinValue, 0) * a + (Random.Next(-1, int.MaxValue) + 1) * (1 - a);
}
Run Code Online (Sandbox Code Playgroud)