Answers:
在Random
类用于创建随机数。(当然是伪随机的。)。
例:
Random rnd = new Random();
int month = rnd.Next(1, 13); // creates a number between 1 and 12
int dice = rnd.Next(1, 7); // creates a number between 1 and 6
int card = rnd.Next(52); // creates a number between 0 and 51
如果要创建多个随机数,则应保留该Random
实例并重新使用它。如果创建的新实例在时间上过于接近,则它们将产生与从系统时钟中植入随机生成器相同的一系列随机数。
rnd
as 声明为static
和/或将其设置一次。
Random
...
Random
使您的随机性更强大:ericlippert.com/2019/02/04/fixing-random-part-2和codeblog.jonskeet.uk/2009/11/04/revisiting -随机性。
这个问题看起来很简单,但是答案有点复杂。如果您看到几乎每个人都建议使用Random类,而有些人则建议使用RNG加密类。但是然后什么时候选择什么。
为此,我们需要首先了解术语“随机性”及其背后的原理。
我鼓励您使用C#https://www.youtube.com/watch?v= tCYxc-2-3fY观看有关RANDOMNESS原理的视频。
首先,我们要了解随机性的原理。当我们告诉某人在红色,绿色和黄色之间进行选择时,内部会发生什么。是什么使人们选择红色,黄色或绿色?
一些初步的想法进入决定他选择的人的思想,它可以是喜欢的颜色,幸运的颜色等。换句话说,我们在RANDOM中将其称为SEED的初始触发器。SEED是起点,促使他选择RANDOM值的触发器。
现在,如果易于猜测SEED,则将这些随机数称为PSEUDO,而当难以猜测种子时,将这些随机数称为 SECURED随机数。
例如,一个人选择的颜色取决于天气和声音的组合,那么很难猜出初始种子。
现在让我发表重要的声明:
*“ Random”类仅生成PSEUDO随机数,而要生成SECURE随机数,我们需要使用“ RNGCryptoServiceProvider”类。
随机类从CPU时钟中获取种子值,这是非常可预测的。因此,换句话说,C#的RANDOM类生成伪随机数,下面是相同的代码。
**注意:** .NET Core 2.0.0+
在无参数构造函数上使用其他种子:它使用而不是CPU时钟Guid.NewGuid().GetHashCode()
。
var random = new Random();
int randomnumber = random.Next()
而RNGCryptoServiceProvider
该类使用OS熵来生成种子。OS熵是一个随机值,它是使用声音,鼠标单击,键盘定时,温度和温度等生成的。下面是相同的代码。
using (RNGCryptoServiceProvider rg = new RNGCryptoServiceProvider())
{
byte[] rno = new byte[5];
rg.GetBytes(rno);
int randomvalue = BitConverter.ToInt32(rno, 0);
}
要了解OS熵,请观看14:30 https://www.youtube.com/watch?v=tCYxc-2-3fY上的这段视频,其中解释了OS熵的逻辑。因此,简单来说,RNG Crypto会生成SECURE随机数。
RandomNumberGenerator.Create()
而不是调用的构造函数RNGCryptoServiceProvider
。
每次执行new Random()时,它都会被初始化。这意味着在紧密的循环中,您会多次获得相同的值。您应该保留一个Random实例,并在同一实例上继续使用Next。
//Function to get random number
private static readonly Random getrandom = new Random();
public static int GetRandomNumber(int min, int max)
{
lock(getrandom) // synchronize
{
return getrandom.Next(min, max);
}
}
Random
对象。在这两种情况下,我都有相同的随机数。借助Pankaj的方法,这没有发生。也许这是随机的,但我现在对此表示怀疑。我正在从不同的线程查询同一秒的随机数。
注意new Random()
当前时间戳上的种子。
如果只想生成一个数字,则可以使用:
new Random().Next( int.MinValue, int.MaxValue )
有关更多信息,请查看Random类,但请注意:
但是,由于时钟具有有限的分辨率,因此使用无参数构造函数连续创建不同的Random对象会创建随机数生成器,该生成器会生成相同的随机数序列
因此,请勿使用此代码生成一系列随机数。
new Random()
循环使用是重要的一点。
我想添加一个加密安全的版本:
RNGCryptoServiceProvider类(MSDN或dotnetperls)
它实现IDisposable。
using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
{
byte[] randomNumber = new byte[4];//4 for int32
rng.GetBytes(randomNumber);
int value = BitConverter.ToInt32(randomNumber, 0);
}
您可以在他为伪随机数构建的MiscUtil类库中使用Jon Skeet的StaticRandom方法。
using MiscUtil;
...
for (int i = 0; i < 100;
Console.WriteLine(StaticRandom.Next());
我尝试了所有这些解决方案,但不包括COBOL答案...大声笑
这些解决方案都不够好。我需要快速进行int循环的随机处理,即使在很宽的范围内,我也得到大量重复值。在为某种随机结果解决了太长时间之后,我决定最终一劳永逸地解决这个问题。
都是关于种子的。
我通过解析Guid中的非数字来创建随机整数,然后使用该实例化我的Random类。
public int GenerateRandom(int min, int max)
{
var seed = Convert.ToInt32(Regex.Match(Guid.NewGuid().ToString(), @"\d+").Value);
return new Random(seed).Next(min, max);
}
更新:如果您一次实例化Random类,则无需播种。因此,最好创建一个静态类并从中调用一个方法。
public static class IntUtil
{
private static Random random;
private static void Init()
{
if (random == null) random = new Random();
}
public static int Random(int min, int max)
{
Init();
return random.Next(min, max);
}
}
然后,您可以像这样使用静态类。
for(var i = 0; i < 1000; i++)
{
int randomNumber = IntUtil.Random(1,100);
Console.WriteLine(randomNumber);
}
我承认我更喜欢这种方法。
内置Random
类(System.Random)生成的数字生成伪随机数。
如果您想要真正的随机数,我们可以得到的最接近的是“安全伪随机生成器”,可以通过使用C#中的Cryptographic类(例如)来生成RNGCryptoServiceProvider
。
即使这样,如果仍然需要真正的随机数,则将需要使用外部源(例如将放射性衰变考虑在内的设备)作为随机数生成器的种子。根据定义,由于纯粹由算法手段生成的任何数字都不能真正地是随机的。
创建一个随机对象
Random rand = new Random();
并使用它
int randomNumber = rand.Next(min, max);
您不必new Random()
每次都需要一个随机数时进行初始化,可以启动一个随机数,然后在循环内或其他任意次数使用它
new Random()
使用当前的刻度作为种子。当您在同一毫秒内实例化多个实例(而不是滴答声)时,您将获得返回的相同值。
从这里修改答案。
如果您有权访问兼容Intel Secure Key的CPU,则可以使用以下库生成实际的随机数和字符串:https : //github.com/JebteK/RdRand和https://www.rdrand.com/
只需从此处下载最新版本,包括Jebtek.RdRand并为其添加using语句即可。然后,您需要做的就是:
// Check to see if this is a compatible CPU
bool isAvailable = RdRandom.GeneratorAvailable();
// Generate 10 random characters
string key = RdRandom.GenerateKey(10);
// Generate 64 random characters, useful for API keys
string apiKey = RdRandom.GenerateAPIKey();
// Generate an array of 10 random bytes
byte[] b = RdRandom.GenerateBytes(10);
// Generate a random unsigned int
uint i = RdRandom.GenerateUnsignedInt();
如果没有兼容的CPU来执行代码,只需使用rdrand.com上的RESTful服务即可。使用项目中包含的RdRandom包装器库,您只需要这样做(注册时可获得1000个免费呼叫):
string ret = Randomizer.GenerateKey(<length>, "<key>");
uint ret = Randomizer.GenerateUInt("<key>");
byte[] ret = Randomizer.GenerateBytes(<length>, "<key>");
没关系的时候:
Random random = new Random();
int randomNumber = random.Next()
您通常希望控制限制(最小和最大木材)。因此,您需要指定随机数的开始和结束位置。
该Next()
方法接受两个参数min和max。
因此,如果我希望我的随机数介于5到15之间,
int randomNumber = random.Next(5, 16)
这是我使用的课程。像RandomNumber.GenerateRandom(1, 666)
internal static class RandomNumber
{
private static Random r = new Random();
private static object l = new object();
private static Random globalRandom = new Random();
[ThreadStatic]
private static Random localRandom;
public static int GenerateNewRandom(int min, int max)
{
return new Random().Next(min, max);
}
public static int GenerateLockedRandom(int min, int max)
{
int result;
lock (RandomNumber.l)
{
result = RandomNumber.r.Next(min, max);
}
return result;
}
public static int GenerateRandom(int min, int max)
{
Random random = RandomNumber.localRandom;
if (random == null)
{
int seed;
lock (RandomNumber.globalRandom)
{
seed = RandomNumber.globalRandom.Next();
}
random = (RandomNumber.localRandom = new Random(seed));
}
return random.Next(min, max);
}
}
我想演示每次使用一个新的随机数生成器时会发生什么。假设您有两个方法或两个类,每个都需要一个随机数。天真地将它们编码为:
public class A
{
public A()
{
var rnd=new Random();
ID=rnd.Next();
}
public int ID { get; private set; }
}
public class B
{
public B()
{
var rnd=new Random();
ID=rnd.Next();
}
public int ID { get; private set; }
}
您认为您会得到两个不同的ID吗?不
class Program
{
static void Main(string[] args)
{
A a=new A();
B b=new B();
int ida=a.ID, idb=b.ID;
// ida = 1452879101
// idb = 1452879101
}
}
解决方案是始终使用单个静态随机生成器。像这样:
public static class Utils
{
public static readonly Random random=new Random();
}
public class A
{
public A()
{
ID=Utils.random.Next();
}
public int ID { get; private set; }
}
public class B
{
public B()
{
ID=Utils.random.Next();
}
public int ID { get; private set; }
}
RNGCryptoServiceProvider
还是更好的选择。
对于强随机种子,我始终使用CryptoRNG而不是Time。
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);
}
}
}
只是作为注释,以供将来参考。
如果您使用的是.NET Core,则多个Random实例并不像以前那样危险。我知道这个问题是2010年提出的,但是由于这个问题年代久远但具有一定吸引力,因此我认为记录这一变化是一件好事。
您可以参考我前一段时间提出的这个问题:
基本上,他们已将默认种子从更改Environment.TickCount
为Guid.NewGuid().GetHashCode()
,因此,如果您创建2个Random实例,它将不会显示相同的数字。
您可以在此处查看来自.NET Framework / .NET Core(2.0.0+)的文件差异: https //github.com/dotnet/coreclr/pull/2192/commits/9f6a0b675e5ac0065a268554de49162c539ff66d
它不如RNGCryptoServiceProvider安全,但至少不会给您带来奇怪的结果。
Interop.GetRandomBytes((byte*)&result, sizeof(int));
。
根据定义,计算机通过确定性过程计算出的数字不能是随机的。
如果您想要一个真正的随机数,则随机性来自大气噪声或放射性衰变。
您可以尝试例如RANDOM.ORG(它会降低性能)
Random rand = new Random();
int name = rand.Next()
将所需的任何值放在第二个括号中,以确保通过编写prop和double选项卡生成代码来设置名称
如果您希望CSRNG生成介于最小值和最大值之间的随机数,那么这是给您的。它将Random
使用安全的随机种子初始化类。
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);
}
}
抱歉,OP确实需要一个随机int
值,但是出于共享知识的简单目的,如果您想要一个随机BigInteger
值,可以使用以下语句:
BigInteger randomVal = BigInteger.Abs(BigInteger.Parse(Guid.NewGuid().ToString().Replace("-",""), NumberStyles.AllowHexSpecifier));
我将假设您想要一个均匀分布的随机数生成器,如下所示。大多数编程语言(包括C#和C ++)中的随机数在使用它们之前均未正确混洗。这意味着您将一遍又一遍地得到相同的数字,这并不是真正随机的。为了避免一遍又一遍地绘制相同的数字,您需要一个种子。通常,此任务的时间间隔是可以的。请记住,如果每次使用相同的种子,您将一遍又一遍地获得相同的数字。因此,请始终尝试使用变化的种子。时间是种籽的好来源,因为它们总是不断变化。
int GetRandomNumber(int min, int max)
{
Random rand = new Random((int)DateTime.Now.Ticks);
return rand.Next(min, max);
}
如果您正在寻找用于正态分布的随机数生成器,则可以使用Box-Muller变换。检查随机高斯变量问题中yoyoyoyosef的答案。由于需要整数,因此必须在末尾将双精度值转换为整数。
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)
最简单的方法可能就是Random.range(1, 3)
生成1到2之间的数字。
您可以尝试使用以下随机种子值:
var rnd = new Random(11111111); //note: seed value is 11111111
string randomDigits = rnd.Next();
var requestNumber = $"SD-{randomDigits}";
为什么不使用int randomNumber = Random.Range(start_range, end_range)
?
重复使用一个随机实例
// Somewhat better code...
Random rng = new Random();
for (int i = 0; i < 100; i++)
{
Console.WriteLine(GenerateDigit(rng));
}
...
static int GenerateDigit(Random rng)
{
// Assume there'd be more logic here really
return rng.Next(10);
}
本文探讨了为什么随机性会导致如此多的问题,以及如何解决这些问题。 http://csharpindepth.com/Articles/Chapter12/Random.aspx
Random
不是线程安全类。如果创建单个实例,则应在锁定机制之后限制对其的访问。
请尝试以下简单步骤来创建随机数:
创建函数:
private int randomnumber(int min, int max)
{
Random rnum = new Random();
return rnum.Next(min, max);
}
在要使用随机数的位置使用上述功能。假设您要在文本框中使用它。
textBox1.Text = randomnumber(0, 999).ToString();
最小值为0,最大值为999。您可以将值更改为所需的任何值。
我总是有生成随机数的方法,这些方法可用于各种目的。我希望这对您也有帮助:
public class RandomGenerator
{
public int RandomNumber(int min, int max)
{
var random = new Random();
return random.Next(min, max);
}
public string RandomString(int size, bool lowerCase)
{
var builder = new StringBuilder();
var random = new Random();
char ch;
for (int i = 0; i < size; i++)
{
ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
builder.Append(ch);
}
if (lowerCase)
return builder.ToString().ToLower();
return builder.ToString();
}
}