生成随机uint

时间:2013-06-13 05:56:00

标签: c# random uint

我需要生成范围为byteushortsbyteshortintuint的随机数。我能够使用C#中的Random方法生成所有这些类型(例如values.Add((int)(random.Next(int.MinValue + 3, int.MaxValue - 2)));),除了uint,因为Random.Next仅接受int值。

是否有一种简单的方法可以生成随机uint

4 个答案:

答案 0 :(得分:21)

最简单的方法可能是使用两个调用:一个用于30位,一个用于最后两个。该答案的早期版本假设Random.Next()包含上限为int.MaxValue,但事实证明它是独占的 - 因此我们只能得到30个统一位。

uint thirtyBits = (uint) random.Next(1 << 30);
uint twoBits = (uint) random.Next(1 << 2);
uint fullRange = (thirtyBits << 2) | twoBits;

(当然,你可以把它当作两个16位值,作为替代......或者介于两者之间的各种选项。)

或者,您可以使用NextBytes填充4字节数组,然后使用BitConverter.ToUInt32

答案 1 :(得分:16)

何塞的日光骰子

  

或者有一种简单的方法可以生成真正的随机uint吗?

我承认,这不是OQ。很明显,有更快的方法来生成不是真实的随机uints。尽管如此,我认为没有人对产生这些产品太感兴趣,除非由于某种原因需要非平面分布。让我们从一些研究开始,让它在C#中变得简单快捷。当我编写代码时,简单快速通常表现得像是同义词。

第一:一些重要的属性

请参阅MSDN

Random构造函数:

  • Random():使用与时间相关的默认种子值初始化Random类的新实例。
  • Random(int seed):使用指定的种子值初始化Random类的新实例。

要提高性能,请创建一个Random对象以随时间生成许多随机数,而不是重复创建新的Random对象以生成一个随机数,因此:

private static Random rand = new Random();

Random方法:

  • rand.Next():返回一个大于或等于零的正随机数,小于int.MaxValue
  • rand.Next(int max):返回一个正的随机数,大于或等于零,小于最大值,max必须大于或等于零。
  • rand.Next(int min, int max):返回一个正的随机数,大于或等于min,小于max,max必须大于或等于min。

家庭作业表明,rand.Next()的速度约为rand.Next(int max)的两倍。

第二:解决方案。

假设一个正int只有两位,忘记符号位,它为零,rand.Next()以相同的概率返回三个不同的值:

00
01
10

对于一个真正的随机数,最低位经常为零,对于最高位是相同的 要使它适用于最低位使用:rand.Next(2)

假设int有三位,rand.Next()返回七个不同的值:

000
001
010
011
100
101
110

要使其适用于最低两位,请使用:rand.Next(4)

假设int具有 n 位 要使其适用于 n 位,请使用:rand.Next(1 << n)

要使其最多使用30位,请使用:rand.Next(1 << 30)
它是最大值,1&lt;&lt; 31大于int.MaxValue

这导致了一种生成真正的随机uint的方法:

private static uint rnd32()
{
    return (uint)(rand.Next(1 << 30)) << 2 | (uint)(rand.Next(1 << 2));
}
  

快速检查:产生零的几率是多少?

1&lt;&lt; 2 = 4 = 2 2 ,1&lt;&lt; 30 = 2 30

零的机会是:1/2 2 * 1/2 30 = 1/2 32 总数,包括零:2 32
它像白昼一样清晰,没有烟雾警报,不是吗?

最后:一个误导性的想法。

是否可以使用rand.Next()

更快地完成此操作
                            int.Maxvalue is:    (2^31)-1
   The largest value rand.Next() returns is:    (2^31)-2 
                           uint.MaxValue is:    (2^32)-1

当使用rand.Next()两次并添加结果时,可能的最大值为:

2*((2^31)-2) = (2^32)-4 

与uint.MaxValue的区别在于:

(2^32)-1 - ((2^32)-4) = 3

要获得uint.MaxValue,必须添加另一个值rand.Next(4),因此我们得到:

rand.Next()+ rand.Next()+ rand.Next(4)

  

产生零的几率是多少?

大概:1/2 31 * 1/2 31 * 1/4 = 1/2 64 ,它应该是1 / 2 32

等一下,怎么样:

2 * rand.Next() + rand.Next(4)
  

再次,有什么机会产生零?

大概:1/2 31 * 1/4 = 1/2 33 ,太小而不能真正随机。

另一个简单的例子:

rand.Next(2) + rand.Next(2),所有可能的结果:

       0 + 0 = 0
       0 + 1 = 1
       1 + 0 = 1
       1 + 1 = 2

平等概率?没办法José。

  

结论:添加真随机数给出一个随机数,但不是真正的随机数。扔两个公平的骰子......

答案 2 :(得分:3)

生成随机 uint 的最简单方法:

uint ui = (uint) new Random().Next(-int.MaxValue, int.MaxValue);

答案 3 :(得分:0)

使用System.Random设置范围,“uint u0&lt; =返回值&lt; = uint u1”

从“零”(包括)到“u”(包括)的范围开始更容易 你可以看看我的另一个 answer. 如果您对更快/更有效的方式感兴趣:
Uniform pseudo random numbers in a range.(这是很多代码/文本)。

在“rnd32(uint u)”下面返回:0&lt; = value&lt; = u。
最困难的情况是:“u = int.MaxValue”。然后是“do-loops”的第一次迭代的机会 (外部和内部“do-loop”的单次迭代),返回有效值为50%  经过两次迭代后,机率为75%等。

外部“do-loop”迭代不止一次的可能性很小 在“u = int.MaxValue”的情况下:0%。

很明显:“rnd32(uint u0,uint u1)”返回u0(incl)和u1(incl)之间的值。

private static Random rand = new Random();

private static uint rnd32(uint u)                                 //  0 <= x <= u
{
    uint x;
    if (u < int.MaxValue) return (uint)rand.Next((int)u + 1);
    do                                         
    {
        do x = (uint)rand.Next(1 << 30) << 2;
        while (x > u);
        x |= (uint)rand.Next(1 << 2);
    }
    while (x > u);
    return x;
}

private static uint rnd32(uint u0, uint u1)                      // set the range
{
    return u0 < u1 ? u0 + rnd32(u1 - u0) : u1 + rnd32(u0 - u1);
}