C#でランダムな整数を生成する方法
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
インスタンスを保存し、それを再利用するべきです。時間的に近すぎる新しいインスタンスを作成すると、それらはシステムジェネレータからランダムジェネレータがシードされるのと同じ一連の乱数を生成します。
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クラスを使用することを推奨しており、一部はRNG暗号クラスを使用することを推奨しています。しかし、それから何を選択するか。
そのためには、まず「ランダム」という用語とその背後にある哲学を理解する必要があります。
C# を使用してRANDOMNESSの哲学の奥深くにあるこのビデオを観ることをお勧めします。https://www.youtube.com/watch?v=tCYxc-2-3fY
最初に、RANDOMNESSの哲学を理解しましょう。ある人にRED、GREEN、YELLOWの中から選ぶように言うと、内部で何が起こるのか。人が赤、黄、緑を選ぶ理由は何ですか?
いくつかの最初の考えは彼の選択を決定する人の心に入ります、それは好きな色、ラッキーカラーなどになります。言い換えれば、我々がRANDOMでSEEDと呼ぶ最初のトリガー。このSEEDは開始点であり、彼にRANDOM値を選択するように促すトリガーである。
SEEDが推測しやすい場合は、そのような乱数は _ pseudo _ と呼ばれ、シードが推測しにくい場合は _ secure _ 乱数と呼ばれます。 。
例えば、人が選択するのは天候と音の組み合わせによって色が異なるので、最初の種を推測するのは難しいでしょう。
今、私は重要な声明をしてみましょう: -
* "Random"クラスはPSEUDO乱数のみを生成し、SECURE乱数を生成するには "RNGCryptoServiceProvider"クラスを使用する必要があります。
ランダムクラスはあなたのCPUクロックからシード値を取得します。これは非常に予測可能です。つまり、C#のRANDOMクラスは疑似乱数を生成します。以下は同じコードです。
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は安全な乱数を生成します。
現在のタイムスタンプにnew Random()
がシードされていることに注意してください。
1つの数だけを生成したい場合 あなたは使うことができます:
new Random().Next( int.MinValue, int.MaxValue )
詳しくは Random クラスを見てください。
ただし、クロックは有限の解像度を持つため、パラメータのないコンストラクタを使用してさまざまなRandomオブジェクトを連続して作成すると、同じ乱数列を生成する乱数ジェネレータが作成されます。
そのため、このコードを使用して一連の乱数を生成しないでください。
Random r = new Random();
int n = r.Next();
暗号的に安全なバージョンを追加したいです。
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の StaticRandom メソッドをMiscUtilクラスライブラリの中で使うことができます。彼はそれを擬似乱数用に構築しました。
using MiscUtil;
...
for (int i = 0; i < 100;
Console.WriteLine(StaticRandom.Next());
randomオブジェクトを現在のミリ秒でシードして、真の乱数を確保することをお勧めします。それを使用して重複を見つけることはほとんどありません。
Random Rand = new Random(DateTime.Now.Millisecond);
アップデート
new Random()
は現在の目盛りをシードとして使うことを知っていますが、現在のミリ秒を使ったシードはランダムスタートとしてはまだ十分です。
最後に残っているのは、乱数が必要になるたびにnew Random()
を初期化する必要はなく、1つのRandomオブジェクトを初期化してからループ内などで必要な回数だけ使用するということです。
私は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
name__クラス(System.Random)によって生成された数値は、擬似乱数を生成します。
真の乱数が必要な場合は、RNGCryptoServiceProvider
name__のようにC#の暗号化クラスを使用して生成できる「secure Pseudo Random Generator」が最も近いです。
それでも、もしあなたがまだ true random numberが必要であれば、乱数発生器の種として放射性崩壊を説明する装置のような外部の情報源を使う必要があるでしょう。定義上、純粋にアルゴリズム的な方法で生成された数は、真にランダムにはなり得ないからです。
以下のコードを使って乱数を取得します。
var random = new Random((int)DateTime.Now.Ticks);
var randomValue = random.Next(startValue, endValue + 1);
here からの回答を修正しました。
Intel Secure Key互換のCPUにアクセスできる場合は、次のライブラリを使用して実際の乱数と文字列を生成できます。 https://github.com/JebteK/RdRand および https://www.rdrand。 com/
here から最新バージョンをダウンロードし、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>");
これが私が使っているクラスです。 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);
}
}
Random random = new Random ();
int randomNumber = random.Next (lowerBound,upperBound);
これは大丈夫ですが。
Random random = new Random();
int randomNumber = random.Next()
ほとんどの場合、制限(最小数と最大数)を制御する必要があります。そのため、乱数の開始位置と終了位置を指定する必要があります。
Next()
メソッドは、minとmaxの2つのパラメータを受け入れます。
だから私が5と15の間にあるように私の乱数をしたい場合は、私はちょうどいい
int randomNumber = random.Next(5, 16)
決定論的プロセスを通してコンピュータによって計算された数は、定義上、ランダムにはできません。
あなたが本物の乱数を望むならば、その乱雑さは大気の雑音または放射性崩壊から来ます。
あなたは例えばRANDOM.ORGを試すことができます(それはパフォーマンスを低下させます)
毎回新しいランダムジェネレータが使用されたときに何が起こるかを実証したいと思いました。 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を取得すると思いますか? _ nope _
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
}
}
解決策は always 単一の静的乱数生成器を使うことです。このような:
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; }
}
強いランダムシードのために、私はいつも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);
}
}
}
Random Rand = new Random();
int name = Rand.Next()
2番目の括弧に必要な値を入力して、propとdouble tabを書いてコードを生成し、名前を設定したことを確認します。
あなたは以下を使ってランダムなシード値で試すことができます:
var rnd = new Random(11111111); //note: seed value is 11111111
string randomDigits = rnd.Next();
var requestNumber = $"SD-{randomDigits}";
申し訳ありませんが、OPは実際にランダムなint
値を必要としますが、ランダムなBigInteger
値が必要な場合に知識を共有するという単純な目的のために、次のステートメントを使用できます。
BigInteger randomVal = BigInteger.Abs(BigInteger.Parse(Guid.NewGuid().ToString().Replace("-",""), NumberStyles.AllowHexSpecifier));
最も簡単な方法はおそらくRandom.range(1, 3)
です。これは1から2までの数を生成します。
私はあなたが以下のように一様に分布した乱数発生器が欲しいと思うでしょう。 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値をintegerにキャストする必要があります。
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)