web-dev-qa-db-ja.com

C#でランダムな値を生成する

C#のRandomクラスを使用してランダムなInt64値とUInt64値を生成するにはどうすればよいですか?

32
SyncMaster

これでうまくいくはずです。 (これは拡張メソッドであるため、Nextオブジェクトで通常のNextDoubleまたはRandomメソッドを呼び出すのと同じように呼び出すことができます)。

public static Int64 NextInt64(this Random rnd)
{
    var buffer = new byte[sizeof(Int64)];
    rnd.NextBytes(buffer);
    return BitConverter.ToInt64(buffer, 0);
}

代わりに符号なし整数が必要な場合は、どこでもInt64UInt64に置き換えるだけで、すべて正常に機能するはずです。

注:セキュリティまたは生成された数値の望ましいランダム性に関するコンテキストが提供されなかったため(実際、OPはRandomクラスについて具体的に言及しました)、私の例は単にRandomクラスを扱っています。これは、ランダム性( 情報エントロピー として定量化されることが多い)が問題にならない場合に推奨されるソリューションです。興味深いことに、RNGCryptoServiceProviderSystem.Security名前空間で提供されるRNG)に言及している他の回答を参照してください。これは、ほぼ同じように使用できます。

73
Noldorin

Random.NextBytes() および BitConverter.ToInt64 / BitConverter.ToUInt64 を使用します。

// Assume rng refers to an instance of System.Random
byte[] bytes = new byte[8];
rng.NextBytes(bytes);
long int64 = BitConverter.ToInt64(bytes, 0);
ulong uint64 = BitConverter.ToUInt64(bytes, 0);

Random.Next() を2回使用し、1つの値をシフトしてから、ORing/addingが機能しないことに注意してください。 Random.Next()は非負の整数のみを生成します。つまり、32ではなく31ビットを生成するため、2回の呼び出しの結果は、Int64/UInt64の全範囲をカバーするために必要な64ビットではなく、62のランダムビットのみを生成します。 ( Guffaの答えRandom.Next()への3つの呼び出しでそれを行う方法を示しています。)

29
Jon Skeet

ここでは、これはcrytpo services(Randomクラスではありません)を使用します。これは(理論的には)より優れたRNGです。ランダムクラス。これをRandomの拡張にすることも、RNGCryptoServiceProviderがクラスレベルのオブジェクトである独自のRandomクラスを作成することも簡単にできます。

using System.Security.Cryptography;
public static Int64 NextInt64()
{
   var bytes = new byte[sizeof(Int64)];    
   RNGCryptoServiceProvider Gen = new RNGCryptoServiceProvider();
   Gen.GetBytes(bytes);    
   return BitConverter.ToInt64(bytes , 0);        
}
9
Muad'Dib

ビットシフトを使用して、31ビットの乱数から64ビットの乱数を組み合わせることができますが、十分なビットを取得するには、3つの31ビットの数値を使用する必要があります。

long r = rnd.Next();
r <<= 31;
r |= rnd.Next();
r <<= 31;
r |= rnd.Next();
6
Guffa

私は常にこれを使用してランダムシードを取得します(簡潔にするためにエラーチェックを削除しました):

m_randomURL = "https://www.random.org/cgi-bin/randnum?num=1&min=1&max=1000000000";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(m_randomURL);
StreamReader stIn = new StreamReader(req.GetResponse().GetResponseStream());
Random Rand = new Random(Convert.ToInt32(stIn.ReadToEnd()));

random.orgは、大気ノイズを使用してランダム性を生成し、宝くじなどに使用されているようです。

5
sipwiz

これらの乱数をどのように使用するかは言いません...Randomによって返される値は「暗号的に安全」ではなく、(を含むものには使用しないでください。大きな)秘密または(たくさんの)お金。

3
Ðаn

byte 配列を作成し、ランダムデータで埋めてから、 longInt64)および longUInt64)。

byte[] buffer = new byte[sizeof(Int64)];
Random random = new Random();

random.NextBytes(buffer);
long signed = BitConverter.ToInt64(buffer, 0);

random.NextBytes(buffer);
long unsigned = BitConverter.ToUInt64(buffer, 0);
1
Samuel

RNGCryptoServiceProviderの代わりにRandomを使用した別の回答。ここでは、結果が常にポジティブになるようにMSBを削除する方法を確認できます。

public static Int64 NextInt64()
{
    var buffer = new byte[8];
    new RNGCryptoServiceProvider().GetBytes(buffer);
    return BitConverter.ToInt64(buffer, 0) & 0x7FFFFFFFFFFFFFFF;
}
0
sventevit