如何在C#中生成随机整数?


当前回答

如果您希望CSRNG生成最小值和最大值之间的随机数,这是适合您的。它将使用安全的随机种子初始化随机类。

    class SecureRandom : Random
    {
        public static byte[] GetBytes(ulong length)
        {
            RNGCryptoServiceProvider RNG = new RNGCryptoServiceProvider();
            byte[] bytes = new byte[length];
            RNG.GetBytes(bytes);
            RNG.Dispose();
            return bytes;
        }
        public SecureRandom() : base(BitConverter.ToInt32(GetBytes(4), 0))
        {

        }
        public int GetRandomInt(int min, int max)
        {
            int treashold = max - min;
            if(treashold != Math.Abs(treashold))
            {
                throw new ArithmeticException("The minimum value can't exceed the maximum value!");
            }
            if (treashold == 0)
            {
                throw new ArithmeticException("The minimum value can't be the same as the maximum value!");
            }
            return min + (Next() % treashold);
        }
        public static int GetRandomIntStatic(int min, int max)
        {
            int treashold = max - min;
            if (treashold != Math.Abs(treashold))
            {
                throw new ArithmeticException("The minimum value can't exceed the maximum value!");
            }
            if(treashold == 0)
            {
                throw new ArithmeticException("The minimum value can't be the same as the maximum value!");
            }
            return min + (BitConverter.ToInt32(GetBytes(4), 0) % treashold);
        }
    }

其他回答

根据定义,由计算机通过确定性过程计算的数字不能是随机的。

如果你想要一个真正的随机数,随机性来自大气噪声或放射性衰变。

例如,您可以尝试RANDOM.ORG(它会降低性能)

对于强随机种子,我总是使用CryptoRNG而不是时间。

using System;
using System.Security.Cryptography;

public class Program
{
    public static void Main()
    {
        var random = new Random(GetSeed());
        Console.WriteLine(random.Next());
    }

    public static int GetSeed() 
    {
        using (var rng = new RNGCryptoServiceProvider())
        {
            var intBytes = new byte[4];
            rng.GetBytes(intBytes);
            return BitConverter.ToInt32(intBytes, 0);
        }
    }
}

我假设你想要一个均匀分布的随机数生成器,如下所示。包括C#和C++在内的大多数编程语言中的随机数在使用之前都没有正确地进行混洗。这意味着你会一次又一次地得到相同的数字,这并不是随机的。为了避免反复绘制相同的数字,您需要一个种子。通常,此任务的时间刻度是正常的。记住,如果你每次使用相同的种子,你会得到相同的数字。所以尽量使用不同的种子。时间是种子的好来源,因为它们总是变化。

int GetRandomNumber(int min, int max)
{
    Random rand = new Random((int)DateTime.Now.Ticks);
    return rand.Next(min, max);
}

如果您正在寻找正态分布的随机数生成器,可以使用Box-Muller变换。检查随机高斯变量问题中yoyoyosef的答案。因为需要整数,所以必须在末尾将双精度值转换为整数。

Random rand = new Random(); //reuse this if you are generating many
double u1 = 1.0-rand.NextDouble(); //uniform(0,1] random doubles
double u2 = 1.0-rand.NextDouble();
double randStdNormal = Math.Sqrt(-2.0 * Math.Log(u1)) *
         Math.Sin(2.0 * Math.PI * u2); //random normal(0,1)
double randNormal =
         mean + stdDev * randStdNormal; //random normal(mean,stdDev^2)

随机高斯变量

仅供参考。

如果您使用的是.NETCore,多个Random实例不会像以前那样危险。我知道这个问题是从2010年开始的,但由于这个问题很老,但有一些吸引力,我认为记录这一变化是一件好事。

你可以参考一下我刚才提出的这个问题:

Microsoft是否更改了随机默认种子?

基本上,他们已经将默认种子从Environment.TickCount更改为Guid.NewGuid().GetHashCode(),因此如果创建两个Random实例,它不应该显示相同的数字(1:4亿)。

您可以在此处查看.NET Framework/.NET Core(2.0.0+)的文件差异:https://github.com/dotnet/coreclr/pull/2192/commits/9f6a0b675e5ac0065a268554de49162c539ff66d

它不像RNGCryptoServiceProvider那样安全,但至少不会给你带来奇怪的结果。


作者@Enigmatility:

这已经过时了。反对使用Guids的声音相当强烈。代码现在是Interop.GetRandomBytes((byte*)&result,sizeof(int));

您可以在他为伪随机数构建的MiscUtil类库中使用JonSkeet的StaticRandom方法。

using MiscUtil;
...

for (int i = 0; i < 100; 
    Console.WriteLine(StaticRandom.Next());