Câu trả lời:
Các Random
lớp học được sử dụng để tạo ra số ngẫu nhiên. (Giả ngẫu nhiên đó là tất nhiên.).
Thí dụ:
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
Nếu bạn định tạo nhiều hơn một số ngẫu nhiên, bạn nên giữ lại Random
thể hiện và sử dụng lại nó. Nếu bạn tạo các thể hiện mới quá gần với thời gian, chúng sẽ tạo ra một chuỗi các số ngẫu nhiên giống như trình tạo ngẫu nhiên được gieo từ đồng hồ hệ thống.
rnd
là static
và / hoặc đặt nó chỉ một lần khi khởi tạo mã.
Random
...
Random
ngoài kia để làm cho tính ngẫu nhiên của bạn mạnh mẽ hơn: ericlippert.com/2019/02/04/fixing-random-part-2 và codeblog.jonskeet.uk/2009/11/04/revisiting tính đồng nhất .
Câu hỏi có vẻ rất đơn giản nhưng câu trả lời hơi phức tạp. Nếu bạn thấy hầu hết mọi người đều đề nghị sử dụng lớp Ngẫu nhiên và một số người đã đề xuất sử dụng lớp tiền điện tử RNG. Nhưng khi nào thì chọn cái gì.
Vì vậy, trước tiên chúng ta cần hiểu thuật ngữ RANDOMNESS và triết lý đằng sau nó.
Tôi sẽ khuyến khích bạn xem video này đi sâu vào triết lý của RANDOMNESS bằng C # https://www.youtube.com/watch?v=tCYxc-2-3fY
Điều đầu tiên cho chúng tôi hiểu triết lý của RANDOMNESS. Khi chúng tôi nói với một người để lựa chọn giữa ĐỎ, XANH và VÀNG những gì xảy ra trong nội bộ. Điều gì khiến một người chọn ĐỎ hoặc VÀNG hoặc XANH?
Một số suy nghĩ ban đầu đi vào tâm trí người quyết định lựa chọn của mình, đó có thể là màu sắc yêu thích, màu may mắn và vân vân. Nói cách khác, một số kích hoạt ban đầu mà chúng tôi gọi là RANDOM là SEED. SEED này là điểm bắt đầu, kích hoạt kích thích anh ta chọn giá trị RANDOM.
Bây giờ nếu một SEED dễ đoán thì những loại số ngẫu nhiên đó được gọi là PSEUDO và khi một hạt giống khó đoán những số ngẫu nhiên đó được gọi là số ngẫu nhiên được BẢO MẬT .
Ví dụ, một người chọn màu sắc tùy thuộc vào thời tiết và sự kết hợp âm thanh thì sẽ rất khó đoán hạt giống ban đầu.
Bây giờ hãy để tôi đưa ra một tuyên bố quan trọng: -
* Lớp Random Random chỉ tạo số ngẫu nhiên PSEUDO và để tạo số ngẫu nhiên AN TOÀN, chúng ta cần sử dụng lớp RNGCryptoServiceProvider.
Lớp ngẫu nhiên lấy các giá trị hạt giống từ đồng hồ CPU của bạn, điều này rất dễ đoán. Vì vậy, nói cách khác, lớp RANDOM của C # tạo ra các số ngẫu nhiên giả, bên dưới là mã cho cùng.
** Lưu ý: ** .NET Core 2.0.0+
sử dụng một hạt giống khác trên hàm tạo không tham số: thay vì xung nhịp CPU mà nó sử dụng Guid.NewGuid().GetHashCode()
.
var random = new Random();
int randomnumber = random.Next()
Trong khi RNGCryptoServiceProvider
lớp sử dụng entropy OS để tạo hạt giống. Entropy của hệ điều hành là một giá trị ngẫu nhiên được tạo bằng âm thanh, nhấp chuột và thời gian bàn phím, nhiệt độ, vv Dưới đây là mã cho cùng.
using (RNGCryptoServiceProvider rg = new RNGCryptoServiceProvider())
{
byte[] rno = new byte[5];
rg.GetBytes(rno);
int randomvalue = BitConverter.ToInt32(rno, 0);
}
Để hiểu entropy của hệ điều hành, hãy xem video này từ 14:30 https://www.youtube.com/watch?v=tCYxc-2-3fY nơi logic của entropy được giải thích. Vì vậy, đặt các từ đơn giản RNG Crypto tạo ra các số ngẫu nhiên AN TOÀN.
RandomNumberGenerator.Create()
thay vì gọi hàm tạo RNGCryptoServiceProvider
vì nó không khả dụng trên tất cả các nền tảng.
Mỗi khi bạn thực hiện Random () mới, nó sẽ được khởi tạo. Điều này có nghĩa là trong một vòng lặp chặt chẽ, bạn nhận được cùng một giá trị rất nhiều lần. Bạn nên giữ một thể hiện ngẫu nhiên duy nhất và tiếp tục sử dụng Next trên cùng một thể hiện.
//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
đối tượng. Trong cả hai trường hợp, tôi nhận được cùng một số ngẫu nhiên. Với cách tiếp cận từ Pankaj, điều đó đã không xảy ra. Có lẽ điều này là ngẫu nhiên , nhưng tôi nghi ngờ nó bây giờ. Tôi đang truy vấn số ngẫu nhiên trong cùng một giây từ các luồng khác nhau.
Coi chừng đó new Random()
là hạt giống trên dấu thời gian hiện tại.
Nếu bạn muốn tạo chỉ một số bạn có thể sử dụng:
new Random().Next( int.MinValue, int.MaxValue )
Để biết thêm thông tin, hãy xem lớp Ngẫu nhiên , tuy nhiên xin lưu ý:
Tuy nhiên, vì đồng hồ có độ phân giải hữu hạn, sử dụng hàm tạo không tham số để tạo các đối tượng Ngẫu nhiên khác nhau liên tiếp sẽ tạo ra các bộ tạo số ngẫu nhiên tạo ra các chuỗi số ngẫu nhiên giống hệt nhau
Vì vậy, không sử dụng mã này để tạo ra một loạt số ngẫu nhiên.
new Random()
trong một vòng lặp là một điểm quan trọng.
Tôi muốn thêm một phiên bản bảo mật bằng mật mã:
Lớp RNGCryptoServiceProvider ( MSDN hoặc dotnetperls )
Nó thực hiện IDis Dùng một lần.
using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
{
byte[] randomNumber = new byte[4];//4 for int32
rng.GetBytes(randomNumber);
int value = BitConverter.ToInt32(randomNumber, 0);
}
Bạn có thể sử dụng phương thức StaticRandom của Jon Skeet bên trong thư viện lớp MiscUtil mà anh ta đã xây dựng cho một số giả ngẫu nhiên.
using MiscUtil;
...
for (int i = 0; i < 100;
Console.WriteLine(StaticRandom.Next());
Tôi đã thử tất cả các giải pháp này trừ câu trả lời của COBOL ... lol
Không có giải pháp nào trong số này là đủ tốt. Tôi cần randoms trong một vòng lặp nhanh và tôi đã nhận được vô số giá trị trùng lặp ngay cả trong phạm vi rất rộng. Sau khi giải quyết loại kết quả ngẫu nhiên quá lâu, cuối cùng tôi quyết định giải quyết vấn đề này một lần và mãi mãi.
Đó là tất cả về hạt giống.
Tôi tạo một số nguyên ngẫu nhiên bằng cách phân tích các chữ số không phải từ Guid, sau đó tôi sử dụng số đó để khởi tạo lớp Random của mình.
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);
}
Cập nhật : Seeding không cần thiết nếu bạn khởi tạo lớp Random một lần. Vì vậy, tốt nhất là tạo một lớp tĩnh và gọi một phương thức tắt nó.
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);
}
}
Sau đó, bạn có thể sử dụng lớp tĩnh như vậy ..
for(var i = 0; i < 1000; i++)
{
int randomNumber = IntUtil.Random(1,100);
Console.WriteLine(randomNumber);
}
Tôi thừa nhận tôi thích cách tiếp cận này tốt hơn.
Các số được tạo bởi inbuilt Random
lớp (System.Random) tạo ra các số ngẫu nhiên giả.
Nếu bạn muốn số ngẫu nhiên thực sự, gần nhất chúng ta có thể nhận được là "Trình tạo ngẫu nhiên giả an toàn" có thể được tạo bằng cách sử dụng các lớp Mật mã trong C #, chẳng hạn như RNGCryptoServiceProvider
.
Mặc dù vậy, nếu bạn vẫn cần các số ngẫu nhiên thực sự, bạn sẽ cần sử dụng một nguồn bên ngoài, chẳng hạn như các thiết bị chiếm sự phân rã phóng xạ làm hạt giống cho một trình tạo số ngẫu nhiên. Vì theo định nghĩa, bất kỳ số nào được tạo ra bởi các phương tiện thuật toán thuần túy không thể thực sự ngẫu nhiên.
tạo một đối tượng ngẫu nhiên
Random rand = new Random();
và sử dụng nó
int randomNumber = rand.Next(min, max);
bạn không phải khởi tạo new Random()
mỗi khi bạn cần một số ngẫu nhiên, bắt đầu một Ngẫu nhiên sau đó sử dụng số đó nhiều lần bạn cần trong một vòng lặp hoặc bất cứ điều gì
new Random()
sử dụng bọ ve hiện tại làm hạt giống. Khi bạn khởi tạo nhiều trường hợp trong cùng một mili giây (trái ngược với đánh dấu), thì bạn sẽ nhận được cùng một giá trị được trả về.
Câu trả lời sửa đổi từ đây .
Nếu bạn có quyền truy cập vào CPU tương thích Intel Secure Key, bạn có thể tạo các số và chuỗi ngẫu nhiên thực bằng các thư viện này: https://github.com/JebteK/RdRand và https://www.rdrand.com/
Chỉ cần tải xuống phiên bản mới nhất từ đây , bao gồm Jebtek.RdRand và thêm một tuyên bố sử dụng cho nó. Sau đó, tất cả những gì bạn cần làm là:
// 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();
Nếu bạn không có CPU tương thích để thực thi mã, chỉ cần sử dụng các dịch vụ RESTful tại rdrand.com. Với thư viện trình bao bọc RdRandom có trong dự án của bạn, bạn chỉ cần thực hiện việc này (bạn nhận được 1000 cuộc gọi miễn phí khi đăng ký):
string ret = Randomizer.GenerateKey(<length>, "<key>");
uint ret = Randomizer.GenerateUInt("<key>");
byte[] ret = Randomizer.GenerateBytes(<length>, "<key>");
Trong khi điều này là ổn:
Random random = new Random();
int randomNumber = random.Next()
Bạn muốn kiểm soát giới hạn (tối thiểu và tối đa mumbers) hầu hết thời gian. Vì vậy, bạn cần xác định nơi số ngẫu nhiên bắt đầu và kết thúc.
Các Next()
phương pháp chấp nhận hai tham số, min và max.
Vì vậy, nếu tôi muốn số ngẫu nhiên của mình nằm trong khoảng từ 5 đến 15, tôi chỉ cần làm
int randomNumber = random.Next(5, 16)
Đây là lớp tôi sử dụng. Hoạt động như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);
}
}
Tôi muốn chứng minh điều gì xảy ra khi một trình tạo ngẫu nhiên mới được sử dụng mỗi lần. Giả sử bạn có hai phương thức hoặc hai lớp, mỗi lớp yêu cầu một số ngẫu nhiên. Và ngây thơ bạn mã họ như:
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; }
}
Bạn có nghĩ rằng bạn sẽ nhận được hai ID khác nhau? CHÂU ÂU
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
}
}
Giải pháp là luôn luôn sử dụng một trình tạo ngẫu nhiên tĩnh duy nhất. Như thế này:
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
dù sao thì cũng là một cuộc gọi tốt hơn.
Đối với hạt giống ngẫu nhiên mạnh, tôi luôn sử dụng CryptoRNG chứ không phải 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);
}
}
}
Random random = new Random ();
int randomNumber = random.Next (lowerBound,upperBound);
Chỉ là một lưu ý để tham khảo trong tương lai.
Nếu bạn đang sử dụng .NET Core, nhiều trường hợp Ngẫu nhiên không còn nguy hiểm như trước. Tôi biết rằng câu hỏi này có từ năm 2010, nhưng vì câu hỏi này đã cũ nhưng có một số điểm thu hút, tôi nghĩ rằng đó là một điều tốt để ghi lại sự thay đổi.
Bạn có thể tham khảo câu hỏi này tôi đã quay lại một lúc:
Microsoft đã thay đổi hạt giống mặc định ngẫu nhiên?
Về cơ bản, họ đã thay đổi hạt giống mặc định từ Environment.TickCount
thànhGuid.NewGuid().GetHashCode()
, vì vậy nếu bạn tạo 2 trường hợp Ngẫu nhiên, nó sẽ không hiển thị cùng một số.
Bạn có thể thấy tệp khác với .NET Framework / .NET Core (2.0.0+) tại đây: https://github.com/dotnet/coreclr/pull/2192/commits/9f6a0b675e5ac0065a268554de49162c539ff66d
Nó không an toàn như RNGCryptoServiceProvider, nhưng ít nhất nó sẽ không mang lại cho bạn kết quả kỳ lạ.
Interop.GetRandomBytes((byte*)&result, sizeof(int));
.
Các số được tính bởi một máy tính thông qua một quy trình xác định, theo định nghĩa, không thể là ngẫu nhiên.
Nếu bạn muốn có một số ngẫu nhiên thực sự, tính ngẫu nhiên đến từ tiếng ồn trong khí quyển hoặc sự phân rã phóng xạ.
Bạn có thể thử ví dụ RANDOM.ORG (nó làm giảm hiệu suất)
Random rand = new Random();
int name = rand.Next()
Đặt bất kỳ giá trị nào bạn muốn trong ngoặc đơn thứ hai, đảm bảo bạn đã đặt tên bằng cách viết prop và tab đôi để tạo mã
Nếu bạn muốn CSRNG tạo số ngẫu nhiên giữa tối thiểu và tối đa, thì đây là dành cho bạn. Nó sẽ khởi tạo Random
các lớp với các hạt ngẫu nhiên an toàn.
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);
}
}
Xin lỗi, OP thực sự yêu cầu một int
giá trị ngẫu nhiên , nhưng với mục đích đơn giản là chia sẻ kiến thức nếu bạn muốn một BigInteger
giá trị ngẫu nhiên, bạn có thể sử dụng câu lệnh sau:
BigInteger randomVal = BigInteger.Abs(BigInteger.Parse(Guid.NewGuid().ToString().Replace("-",""), NumberStyles.AllowHexSpecifier));
Tôi sẽ giả sử rằng bạn muốn một trình tạo số ngẫu nhiên phân phối đồng đều như dưới đây. Số ngẫu nhiên trong hầu hết các ngôn ngữ lập trình bao gồm C # và C ++ không được xáo trộn đúng cách trước khi sử dụng chúng. Điều này có nghĩa là bạn sẽ nhận được cùng một số nhiều lần, điều này không thực sự ngẫu nhiên. Để tránh vẽ cùng một số nhiều lần, bạn cần một hạt giống. Thông thường, đánh dấu thời gian là ok cho nhiệm vụ này. Hãy nhớ rằng bạn sẽ nhận được cùng một số nhiều lần nếu bạn đang sử dụng cùng một hạt giống mỗi lần. Vì vậy, hãy cố gắng sử dụng hạt giống khác nhau luôn. Thời gian là nguồn tốt cho hạt giống vì họ luôn luôn tán gẫu.
int GetRandomNumber(int min, int max)
{
Random rand = new Random((int)DateTime.Now.Ticks);
return rand.Next(min, max);
}
nếu bạn đang tìm kiếm trình tạo số ngẫu nhiên để phân phối bình thường, bạn có thể sử dụng phép chuyển đổi Box-Muller. Kiểm tra câu trả lời của yoyoyoyosef trong Câu hỏi biến ngẫu nhiên Gaussian. Vì bạn muốn số nguyên, bạn phải truyền giá trị gấp đôi cho số nguyên ở cuối.
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)
Cách dễ nhất có lẽ chỉ là Random.range(1, 3)
Điều này sẽ tạo ra một số từ 1 đến 2.
Bạn có thể thử với giá trị hạt ngẫu nhiên bằng cách sử dụng dưới đây:
var rnd = new Random(11111111); //note: seed value is 11111111
string randomDigits = rnd.Next();
var requestNumber = $"SD-{randomDigits}";
Tại sao không sử dụng int randomNumber = Random.Range(start_range, end_range)
?
Sử dụng một trường hợp ngẫu nhiên lặp đi lặp lại
// 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);
}
Bài viết này xem xét tại sao sự ngẫu nhiên gây ra rất nhiều vấn đề và làm thế nào để giải quyết chúng. http://csharpindepth.com/Articles/Ch CHƯƠNG12 / Random.aspx
Random
không phải là một lớp an toàn chủ đề. Nếu bạn tạo một thể hiện đơn lẻ, bạn nên hạn chế quyền truy cập vào nó sau một cơ chế khóa.
Hãy thử các bước đơn giản sau để tạo số ngẫu nhiên:
Tạo chức năng:
private int randomnumber(int min, int max)
{
Random rnum = new Random();
return rnum.Next(min, max);
}
Sử dụng chức năng trên ở một vị trí mà bạn muốn sử dụng các số ngẫu nhiên. Giả sử bạn muốn sử dụng nó trong một hộp văn bản.
textBox1.Text = randomnumber(0, 999).ToString();
0 là tối thiểu và 999 là tối đa. Bạn có thể thay đổi các giá trị thành bất cứ điều gì bạn muốn.
Tôi luôn có các phương thức tạo ra các số ngẫu nhiên giúp cho các mục đích khác nhau. Tôi hy vọng điều này cũng có thể giúp bạn:
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();
}
}
Nhanh chóng và dễ dàng cho nội tuyến, sử dụng mã dưới đây:
new Random().Next(min, max);
// for example unique name
strName += "_" + new Random().Next(100, 999);