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 自体は範囲に含まれません。
例:
コード | コンソール出力 |
---|---|
|
|
しかし、この方法が必要なものではない場合はどうすればよいでしょうか? 6 面体のサイコロを振ることをシミュレートするプログラムを作成するとします。0 ~ 1 の範囲の実数ではなく、1 ~ 6 の範囲のランダムな整数を取得するにはどうすればよいですか?
実はとてもシンプルなのです。
まず、範囲[0, 1)
を にマッピングする必要があります[0, 6)
。random()
これを行うには、によって返された結果を で乗算するだけです6
。もちろん、整数を取得するには、切り上げる必要があります。
コード | コンソール出力 |
---|---|
|
|
は、範囲内getRandomDieNumber()
のランダムな整数を返します0..5
。ただし、それはセット内の数値ではありません1, 2, 3, 4, 5, 6
。セット内の番号となります0, 1, 2, 3, 4, 5
。
セット内の数値が必要な場合は1, 2, 3, 4, 5, 6
、乱数に 1 を追加するだけです。
コード | コンソール出力 |
---|---|
|
|
これで完璧です!
3.Random
クラス
Java には、Random
一連の擬似乱数をカプセル化する特別なクラスがあります。クラスの複数のオブジェクトを作成できますRandom
。これらのオブジェクトはそれぞれ、独自の擬似乱数シーケンスを生成します。
これは、興味深いメソッドがたくさんある非常に興味深いクラスです。最も単純なものから始めましょう。
double nextDouble()
0.0
このメソッドは、範囲-のランダムな実数を返します1.0
。それはMath.random()
方法と非常によく似ています。それもそのはず、Math.random()
メソッドは単にオブジェクトnextDouble()
のメソッドを呼び出すだけですからRandom
。
float nextFloat()
このメソッドは のnextDouble()
メソッドとよく似ていますが、返される乱数は ですfloat
。0.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
GO TO FULL VERSION