1. 擬似乱数

プログラマーは、「特定のリストから映画をランダムに選択する」、「宝くじの当選者を選択する」、「ユーザーがスマートフォンを振るとプレイリストをシャッフルする」、「メッセージを暗号化するための乱数を選択する」など、一見単純なタスクに直面することがあります。など。いずれの場合も、開発者は論理的な質問をします。乱数を取得するにはどうすればよいですか?

実際には、真の乱数を取得することはかなり困難です。実際、これは非常に難しいため、真のランダム性の要件をすべて満たす数値を生成するために、一部のコンピュータには特別な数学的コプロセッサが組み込まれています。

プログラマーは独自の解決策、つまり擬似乱数を考え出しました。擬似乱数は、数値がランダムに見える一種のシーケンスです。ただし、専門家は注意深く分析を実行することで、シーケンス内の特定のパターンを見つけることができます。このような数値は機密文書の暗号化には適していませんが、ゲームでサイコロの目をシミュレートするには十分です。

一連の擬似乱数を生成するアルゴリズムは数多くあります。それらのほとんどすべては、前の数値といくつかの追加のヘルパー数値に基づいて次の乱数を生成します。

たとえば、次のプログラムは1000繰り返さない数値を表示します。

public class Main
{
   public static int a = 41;
   public static int c = 11119;
   public static int m = 11113;
   public static int seed = 1;

   public static int getNextRandom()
   {
     seed = (a * seed + c) % m;
     return seed;
   }

   public static void main(String[] args)
   {
     for (int i = 0; i < 1000; i++)
     {
       System.out.println(getNextRandom());
     }
   }
}

ちなみに、ここでは擬似乱数について話しているのではありません。私たちは一連の擬似乱数について話しています。単一の数値を見ただけでは、それがランダムであるかどうかを判断することはできません。

実際、乱数を取得するにはさまざまな方法があります。

public static int getRandomNumber()
{
   return 4; // Here's a random number (we got it by rolling a die)
}

2.Math.random()

Java では、Mathクラスには乱数を返す特別なメソッドがあります。ご想像のとおり、このメソッドは と呼ばれますrandom。一般に、このメソッドを呼び出すと次のようになります。

Math.random()

0このメソッドはパラメータをとらず、から までの範囲の擬似乱数の実数を返します1。数値 1 自体は範囲に含まれません。

例:

コード コンソール出力
public class Main
{
   public static void main(String[] args)
   {
     for (int i = 0; i < 10; i++)
     {
       System.out.println(Math.random());
     }
   }
}
0.9703753971734451
0.09979423801773157
0.994048474709053
0.2852203204171295
0.13551248551226025
0.3128547131272822
0.5342480554101412
0.6817369932044817
0.1840767788961758
0.06969563435451254

しかし、この方法が必要なものではない場合はどうすればよいでしょうか? 6 面体のサイコロを振ることをシミュレートするプログラムを作成するとします。0 ~ 1 の範囲の実数ではなく、1 ~ 6 の範囲のランダムな整数を取得するにはどうすればよいですか?

実はとてもシンプルなのです。

まず、範囲[0, 1)を にマッピングする必要があります[0, 6)random()これを行うには、によって返された結果を で乗算するだけです6。もちろん、整数を取得するには、切り上げる必要があります。

コード コンソール出力
public class Main
{
   public static int getRandomDieNumber()
   {
      return (int) (Math.random() * 6);
   }

   public static void main(String[] args)
   {
      for (int i = 0; i < 10; i++)
      {
         int x = getRandomDieNumber();
         System.out.println(x);
      }
   }
}
5
2
3
3
2
4
1
1
5
0

は、範囲内getRandomDieNumber()のランダムな整数を返します0..5。ただし、それはセット内の数値ではありません1, 2, 3, 4, 5, 6。セット内の番号となります0, 1, 2, 3, 4, 5

セット内の数値が必要な場合は1, 2, 3, 4, 5, 6、乱数に 1 を追加するだけです。

コード コンソール出力
public class Main
{
   public static int getRandomDieNumber()
   {
      return (int) (Math.random() * 6) + 1;
   }

   public static void main(String[] args)
   {
     for (int i = 0; i < 10; i++)
     {
       int x = getRandomDieNumber();
       System.out.println(x);
     }
   }
}
3
2
1
3
6
5
6
1
6
6

これで完璧です!



3.Randomクラス

Java には、Random一連の擬似乱数をカプセル化する特別なクラスがあります。クラスの複数のオブジェクトを作成できますRandom。これらのオブジェクトはそれぞれ、独自の擬似乱数シーケンスを生成します。

これは、興味深いメソッドがたくさんある非常に興味深いクラスです。最も単純なものから始めましょう。

double nextDouble()

0.0このメソッドは、範囲-のランダムな実数を返します1.0。それはMath.random()方法と非常によく似ています。それもそのはず、Math.random()メソッドは単にオブジェクトnextDouble()のメソッドを呼び出すだけですからRandom

float nextFloat()

このメソッドは のnextDouble()メソッドとよく似ていますが、返される乱数は ですfloat0.0それはまた-の範囲内にあります1.0。また、Java では常にそうであるように、範囲には数値1.0自体は含まれません。

Random r = new Random();
float f = r.nextFloat();

int nextInt(int max)

このメソッドは、範囲内のランダムな整数[0, max)を返します。0は範囲に含まれていますが、max含まれていません。

つまり、 set 内の乱数を取得したい場合は1, 2, 3, 4, 5, 6、返された乱数に 1 を追加する必要があります。

Random r = new Random();
int x = r.nextInt(6) + 1;

int nextInt()

このメソッドは前のメソッドと似ていますが、パラメーターを受け取りません。では、その戻り値の範囲はどれくらいでしょうか? から-2 billionまで+2 billion

正確には、 から-2147483648までです+2147483647

long nextLong()

このメソッドは メソッドに似ていますnextInt()が、戻り値は の可能な範囲全体のどこかに収まりますlong

boolean nextBoolean()

このメソッドはランダムなboolean値、falseまたはを返しますtrue。これは、ランダムなブール値の長いシーケンスを取得する必要がある場合に非常に便利です。

void nextBytes(byte[] data)

このメソッドは何も返しません (戻り値の型が であるためvoid)。代わりに、渡された配列にランダムな値を埋めます。これは、ランダムなデータで満たされた大きなバッファが必要な場合に非常に便利です。

double nextGaussian()

0.0このメソッドは、範囲-のランダムな実数を返します1.0。ただし、数値はこの範囲内で均等に分布しているわけではありません。代わりに、それらは正規分布に従います。

範囲の中央付近の値 ( 0.5) は、範囲の端の値よりも頻繁に発生します。

ランダムクラス

この場合、値の分布のピークは次のとおりです。0.5