回答:
この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
よう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の哲学をさらに詳しく説明したこの動画をご覧になることをお勧めします
最初に、ランダム性の哲学を理解しましょう。RED、GREEN、YELLOWのいずれかを選択するように人に指示すると、内部で何が起きるか。人が赤、黄色、または緑を選択するのはなぜですか?
彼の選択を決定する人の心にいくつかの最初の考えが入ります、それは好きな色、幸運な色などになる可能性があります。言い換えると、ランダムでSEEDと呼ぶ初期トリガーです。このSEEDは開始点であり、ランダム値を選択するようにトリガーします。
今、SEEDは、ランダムな数字のものと種類は次のように呼ばれている推測しやすい場合PSEUDOとするとき、シードは、それらの乱数を推測することは困難であると呼ばれている SECURED乱数を。
たとえば、天気と音の組み合わせに応じて色を選択する人は、最初の種を推測するのが難しいでしょう。
ここで私は重要な声明を出しましょう:-
*「ランダム」クラスはPSEUDO乱数のみを生成します。SECURE乱数を生成するには、「RNGCryptoServiceProvider」クラスを使用する必要があります。
ランダムクラスは、非常に予測可能なCPUクロックからシード値を取得します。つまり、C#のRANDOMクラスは疑似乱数を生成します。以下は同じもののコードです。
**注:** .NET Core 2.0.0+
は、パラメーターなしのコンストラクターで異なるシードを使用しGuid.NewGuid().GetHashCode()
ます。使用するCPUクロックの代わりに。
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エントロピーを理解するには、OSエントロピーのロジックが説明されている14:30 https://www.youtube.com/watch?v=tCYxc-2-3fYからこのビデオを参照してください。したがって、簡単な言葉でRNG暗号は安全な乱数を生成します。
RandomNumberGenerator.Create()
、のコンストラクタを呼び出す代わりにを使用することをお勧めしRNGCryptoServiceProvider
ます。
新しい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
オブジェクトを保存しようとしました。どちらの場合も、同じ乱数を取得しました。パンカジからのアプローチで、それは起こりませんでした。多分これはランダムですが、私は今それを疑っています。異なるスレッドから同じ秒で乱数をクエリしています。
new Random()
現在のタイムスタンプにシードされることに注意してください。
あなたが1つだけ数を生成したいなら、あなたは使うことができます:
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);
}
Jon Skeet が疑似乱数用に作成したMiscUtilクラスライブラリ内でStaticRandomメソッドを使用できます。
using MiscUtil;
...
for (int i = 0; i < 100;
Console.WriteLine(StaticRandom.Next());
私はCOBOLの回答を除いてこれらすべてのソリューションを試しました...笑
これらのソリューションはどれも十分に優れていませんでした。高速for 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 rand = new Random();
そしてそれを使う
int randomNumber = rand.Next(min, max);
new Random()
乱数が必要になるたびに初期化する必要はありません。1つのランダムを開始してから、ループ内などで必要なだけそれを使用します。
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の2つのパラメーターを受け入れます。
ですから、乱数を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);
}
}
毎回新しいランダムジェネレーターを使用するとどうなるかを説明したかったのです。乱数を必要とする2つのメソッドまたは2つのクラスがあるとします。そして単純にあなたはそれらを次のようにコーディングします:
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; }
}
2つの異なる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を使用します。
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を使用している場合、複数のランダムインスタンスは以前ほど危険ではありません。この質問は2010年からのものであることは承知していますが、この質問は古くて魅力がありますので、変更を文書化することは良いことだと思います。
私がしばらく前に作成したこの質問を参照してください:
マイクロソフトはランダムなデフォルトシードを変更しましたか?
基本的に、それらはデフォルトのシードをからEnvironment.TickCount
に変更したGuid.NewGuid().GetHashCode()
ため、ランダムの2つのインスタンスを作成した場合、同じ番号は表示されません。
.NET Framework / .NET Core(2.0.0+)のファイルの差分は、https://github.com/dotnet/coreclr/pull/2192/commits/9f6a0b675e5ac0065a268554de49162c539ff66dで確認できます。
RNGCryptoServiceProviderほど安全ではありませんが、少なくとも奇妙な結果は得られません。
Interop.GetRandomBytes((byte*)&result, sizeof(int));
です。
Random rand = new Random();
int name = rand.Next()
2番目の括弧に任意の値を入力して、propとdouble tabを記述してコードを生成し、名前を設定したことを確認します
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);
}
}
以下のような均一に分散された乱数ジェネレータが必要だと仮定します。C#およびC ++を含むほとんどのプログラミング言語の乱数は、それらを使用する前に適切にシャッフルされません。これは、実際にはランダムではない、同じ数を繰り返し取得することを意味します。同じ数字を何度も描画しないようにするには、シードが必要です。通常、このタスクでは時間のティックは問題ありません。毎回同じシードを使用している場合は、同じ数が何度も繰り返されることに注意してください。したがって、常にさまざまなシードを使用するようにしてください。時間は常に変化するので、時間は種の良い源です。
int GetRandomNumber(int min, int max)
{
Random rand = new Random((int)DateTime.Now.Ticks);
return rand.Next(min, max);
}
正規分布の乱数ジェネレーターを探している場合は、Box-Muller変換を使用できます。ランダムガウス変数の質問のyoyoyoyosefによる回答を確認してください。整数が必要なので、最後にdouble値を整数にキャストする必要があります。
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)
ですか?
ランダムの1つのインスタンスを繰り返し使用する
// 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();
}
}